aboutsummaryrefslogtreecommitdiffstats
path: root/block/blk-cgroup.c
diff options
context:
space:
mode:
Diffstat (limited to 'block/blk-cgroup.c')
-rw-r--r--block/blk-cgroup.c86
1 files changed, 67 insertions, 19 deletions
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
index 266c0707d588..14367499cfed 100644
--- a/block/blk-cgroup.c
+++ b/block/blk-cgroup.c
@@ -422,6 +422,70 @@ void blkiocg_update_io_merged_stats(struct blkio_group *blkg, bool direction,
422} 422}
423EXPORT_SYMBOL_GPL(blkiocg_update_io_merged_stats); 423EXPORT_SYMBOL_GPL(blkiocg_update_io_merged_stats);
424 424
425/**
426 * blkg_free - free a blkg
427 * @blkg: blkg to free
428 *
429 * Free @blkg which may be partially allocated.
430 */
431static void blkg_free(struct blkio_group *blkg)
432{
433 if (blkg) {
434 free_percpu(blkg->stats_cpu);
435 kfree(blkg->pd);
436 kfree(blkg);
437 }
438}
439
440/**
441 * blkg_alloc - allocate a blkg
442 * @blkcg: block cgroup the new blkg is associated with
443 * @q: request_queue the new blkg is associated with
444 * @pol: policy the new blkg is associated with
445 *
446 * Allocate a new blkg assocating @blkcg and @q for @pol.
447 *
448 * FIXME: Should be called with queue locked but currently isn't due to
449 * percpu stat breakage.
450 */
451static struct blkio_group *blkg_alloc(struct blkio_cgroup *blkcg,
452 struct request_queue *q,
453 struct blkio_policy_type *pol)
454{
455 struct blkio_group *blkg;
456
457 /* alloc and init base part */
458 blkg = kzalloc_node(sizeof(*blkg), GFP_ATOMIC, q->node);
459 if (!blkg)
460 return NULL;
461
462 spin_lock_init(&blkg->stats_lock);
463 rcu_assign_pointer(blkg->q, q);
464 blkg->blkcg = blkcg;
465 blkg->plid = pol->plid;
466 cgroup_path(blkcg->css.cgroup, blkg->path, sizeof(blkg->path));
467
468 /* alloc per-policy data */
469 blkg->pd = kzalloc_node(sizeof(*blkg->pd) + pol->pdata_size, GFP_ATOMIC,
470 q->node);
471 if (!blkg->pd) {
472 blkg_free(blkg);
473 return NULL;
474 }
475
476 /* broken, read comment in the callsite */
477 blkg->stats_cpu = alloc_percpu(struct blkio_group_stats_cpu);
478 if (!blkg->stats_cpu) {
479 blkg_free(blkg);
480 return NULL;
481 }
482
483 /* attach pd to blkg and invoke per-policy init */
484 blkg->pd->blkg = blkg;
485 pol->ops.blkio_init_group_fn(blkg);
486 return blkg;
487}
488
425struct blkio_group *blkg_lookup_create(struct blkio_cgroup *blkcg, 489struct blkio_group *blkg_lookup_create(struct blkio_cgroup *blkcg,
426 struct request_queue *q, 490 struct request_queue *q,
427 enum blkio_policy_id plid, 491 enum blkio_policy_id plid,
@@ -463,19 +527,7 @@ struct blkio_group *blkg_lookup_create(struct blkio_cgroup *blkcg,
463 spin_unlock_irq(q->queue_lock); 527 spin_unlock_irq(q->queue_lock);
464 rcu_read_unlock(); 528 rcu_read_unlock();
465 529
466 new_blkg = pol->ops.blkio_alloc_group_fn(q, blkcg); 530 new_blkg = blkg_alloc(blkcg, q, pol);
467 if (new_blkg) {
468 new_blkg->stats_cpu = alloc_percpu(struct blkio_group_stats_cpu);
469
470 spin_lock_init(&new_blkg->stats_lock);
471 rcu_assign_pointer(new_blkg->q, q);
472 new_blkg->blkcg = blkcg;
473 new_blkg->plid = plid;
474 cgroup_path(blkcg->css.cgroup, new_blkg->path,
475 sizeof(new_blkg->path));
476 } else {
477 css_put(&blkcg->css);
478 }
479 531
480 rcu_read_lock(); 532 rcu_read_lock();
481 spin_lock_irq(q->queue_lock); 533 spin_lock_irq(q->queue_lock);
@@ -492,7 +544,7 @@ struct blkio_group *blkg_lookup_create(struct blkio_cgroup *blkcg,
492 goto out; 544 goto out;
493 545
494 /* did alloc fail? */ 546 /* did alloc fail? */
495 if (unlikely(!new_blkg || !new_blkg->stats_cpu)) { 547 if (unlikely(!new_blkg)) {
496 blkg = ERR_PTR(-ENOMEM); 548 blkg = ERR_PTR(-ENOMEM);
497 goto out; 549 goto out;
498 } 550 }
@@ -504,11 +556,7 @@ struct blkio_group *blkg_lookup_create(struct blkio_cgroup *blkcg,
504 pol->ops.blkio_link_group_fn(q, blkg); 556 pol->ops.blkio_link_group_fn(q, blkg);
505 spin_unlock(&blkcg->lock); 557 spin_unlock(&blkcg->lock);
506out: 558out:
507 if (new_blkg) { 559 blkg_free(new_blkg);
508 free_percpu(new_blkg->stats_cpu);
509 kfree(new_blkg);
510 css_put(&blkcg->css);
511 }
512 return blkg; 560 return blkg;
513} 561}
514EXPORT_SYMBOL_GPL(blkg_lookup_create); 562EXPORT_SYMBOL_GPL(blkg_lookup_create);