Skip to content

Commit 4308a43

Browse files
htejunaxboe
authored andcommitted
blkcg: don't offline parent blkcg first
blkcg->cgwb_refcnt is used to delay blkcg offlining so that blkgs don't get offlined while there are active cgwbs on them. However, it ends up making offlining unordered sometimes causing parents to be offlined before children. Let's fix this by making child blkcgs pin the parents' online states. Note that pin/unpin names are chosen over get/put intentionally because css uses get/put online for something different. Signed-off-by: Tejun Heo <[email protected]> Signed-off-by: Jens Axboe <[email protected]>
1 parent d866dbf commit 4308a43

File tree

2 files changed

+21
-1
lines changed

2 files changed

+21
-1
lines changed

block/blk-cgroup.c

+16
Original file line numberDiff line numberDiff line change
@@ -1006,6 +1006,21 @@ blkcg_css_alloc(struct cgroup_subsys_state *parent_css)
10061006
return ret;
10071007
}
10081008

1009+
static int blkcg_css_online(struct cgroup_subsys_state *css)
1010+
{
1011+
struct blkcg *blkcg = css_to_blkcg(css);
1012+
struct blkcg *parent = blkcg_parent(blkcg);
1013+
1014+
/*
1015+
* blkcg_pin_online() is used to delay blkcg offline so that blkgs
1016+
* don't go offline while cgwbs are still active on them. Pin the
1017+
* parent so that offline always happens towards the root.
1018+
*/
1019+
if (parent)
1020+
blkcg_pin_online(parent);
1021+
return 0;
1022+
}
1023+
10091024
/**
10101025
* blkcg_init_queue - initialize blkcg part of request queue
10111026
* @q: request_queue to initialize
@@ -1199,6 +1214,7 @@ static void blkcg_exit(struct task_struct *tsk)
11991214

12001215
struct cgroup_subsys io_cgrp_subsys = {
12011216
.css_alloc = blkcg_css_alloc,
1217+
.css_online = blkcg_css_online,
12021218
.css_offline = blkcg_css_offline,
12031219
.css_free = blkcg_css_free,
12041220
.can_attach = blkcg_can_attach,

include/linux/blk-cgroup.h

+5-1
Original file line numberDiff line numberDiff line change
@@ -436,8 +436,12 @@ static inline void blkcg_pin_online(struct blkcg *blkcg)
436436
*/
437437
static inline void blkcg_unpin_online(struct blkcg *blkcg)
438438
{
439-
if (refcount_dec_and_test(&blkcg->online_pin))
439+
do {
440+
if (!refcount_dec_and_test(&blkcg->online_pin))
441+
break;
440442
blkcg_destroy_blkgs(blkcg);
443+
blkcg = blkcg_parent(blkcg);
444+
} while (blkcg);
441445
}
442446

443447
/**

0 commit comments

Comments
 (0)