Skip to content

Commit 6b06546

Browse files
dennisszhouaxboe
authored andcommitted
Revert "blk-throttle: fix race between blkcg_bio_issue_check() and cgroup_rmdir()"
This reverts commit 4c69948. Destroying blkgs is tricky because of the nature of the relationship. A blkg should go away when either a blkcg or a request_queue goes away. However, blkg's pin the blkcg to ensure they remain valid. To break this cycle, when a blkcg is offlined, blkgs put back their css ref. This eventually lets css_free() get called which frees the blkcg. The above commit (4c69948) breaks this order of events by trying to destroy blkgs in css_free(). As the blkgs still hold references to the blkcg, css_free() is never called. The race between blkcg_bio_issue_check() and cgroup_rmdir() will be addressed in the following patch by delaying destruction of a blkg until all writeback associated with the blkcg has been finished. Fixes: 4c69948 ("blk-throttle: fix race between blkcg_bio_issue_check() and cgroup_rmdir()") Reviewed-by: Josef Bacik <josef@toxicpanda.com> Signed-off-by: Dennis Zhou <dennisszhou@gmail.com> Cc: Jiufei Xue <jiufei.xue@linux.alibaba.com> Cc: Joseph Qi <joseph.qi@linux.alibaba.com> Cc: Tejun Heo <tj@kernel.org> Cc: Jens Axboe <axboe@kernel.dk> Signed-off-by: Jens Axboe <axboe@kernel.dk>
1 parent 52bd456 commit 6b06546

File tree

2 files changed

+16
-63
lines changed

2 files changed

+16
-63
lines changed

block/blk-cgroup.c

Lines changed: 16 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -310,28 +310,11 @@ struct blkcg_gq *blkg_lookup_create(struct blkcg *blkcg,
310310
}
311311
}
312312

313-
static void blkg_pd_offline(struct blkcg_gq *blkg)
314-
{
315-
int i;
316-
317-
lockdep_assert_held(blkg->q->queue_lock);
318-
lockdep_assert_held(&blkg->blkcg->lock);
319-
320-
for (i = 0; i < BLKCG_MAX_POLS; i++) {
321-
struct blkcg_policy *pol = blkcg_policy[i];
322-
323-
if (blkg->pd[i] && !blkg->pd[i]->offline &&
324-
pol->pd_offline_fn) {
325-
pol->pd_offline_fn(blkg->pd[i]);
326-
blkg->pd[i]->offline = true;
327-
}
328-
}
329-
}
330-
331313
static void blkg_destroy(struct blkcg_gq *blkg)
332314
{
333315
struct blkcg *blkcg = blkg->blkcg;
334316
struct blkcg_gq *parent = blkg->parent;
317+
int i;
335318

336319
lockdep_assert_held(blkg->q->queue_lock);
337320
lockdep_assert_held(&blkcg->lock);
@@ -340,6 +323,13 @@ static void blkg_destroy(struct blkcg_gq *blkg)
340323
WARN_ON_ONCE(list_empty(&blkg->q_node));
341324
WARN_ON_ONCE(hlist_unhashed(&blkg->blkcg_node));
342325

326+
for (i = 0; i < BLKCG_MAX_POLS; i++) {
327+
struct blkcg_policy *pol = blkcg_policy[i];
328+
329+
if (blkg->pd[i] && pol->pd_offline_fn)
330+
pol->pd_offline_fn(blkg->pd[i]);
331+
}
332+
343333
if (parent) {
344334
blkg_rwstat_add_aux(&parent->stat_bytes, &blkg->stat_bytes);
345335
blkg_rwstat_add_aux(&parent->stat_ios, &blkg->stat_ios);
@@ -382,7 +372,6 @@ static void blkg_destroy_all(struct request_queue *q)
382372
struct blkcg *blkcg = blkg->blkcg;
383373

384374
spin_lock(&blkcg->lock);
385-
blkg_pd_offline(blkg);
386375
blkg_destroy(blkg);
387376
spin_unlock(&blkcg->lock);
388377
}
@@ -1058,54 +1047,21 @@ static struct cftype blkcg_legacy_files[] = {
10581047
* @css: css of interest
10591048
*
10601049
* This function is called when @css is about to go away and responsible
1061-
* for offlining all blkgs pd and killing all wbs associated with @css.
1062-
* blkgs pd offline should be done while holding both q and blkcg locks.
1063-
* As blkcg lock is nested inside q lock, this function performs reverse
1064-
* double lock dancing.
1050+
* for shooting down all blkgs associated with @css. blkgs should be
1051+
* removed while holding both q and blkcg locks. As blkcg lock is nested
1052+
* inside q lock, this function performs reverse double lock dancing.
10651053
*
10661054
* This is the blkcg counterpart of ioc_release_fn().
10671055
*/
10681056
static void blkcg_css_offline(struct cgroup_subsys_state *css)
10691057
{
10701058
struct blkcg *blkcg = css_to_blkcg(css);
1071-
struct blkcg_gq *blkg;
10721059

10731060
spin_lock_irq(&blkcg->lock);
10741061

1075-
hlist_for_each_entry(blkg, &blkcg->blkg_list, blkcg_node) {
1076-
struct request_queue *q = blkg->q;
1077-
1078-
if (spin_trylock(q->queue_lock)) {
1079-
blkg_pd_offline(blkg);
1080-
spin_unlock(q->queue_lock);
1081-
} else {
1082-
spin_unlock_irq(&blkcg->lock);
1083-
cpu_relax();
1084-
spin_lock_irq(&blkcg->lock);
1085-
}
1086-
}
1087-
1088-
spin_unlock_irq(&blkcg->lock);
1089-
1090-
wb_blkcg_offline(blkcg);
1091-
}
1092-
1093-
/**
1094-
* blkcg_destroy_all_blkgs - destroy all blkgs associated with a blkcg
1095-
* @blkcg: blkcg of interest
1096-
*
1097-
* This function is called when blkcg css is about to free and responsible for
1098-
* destroying all blkgs associated with @blkcg.
1099-
* blkgs should be removed while holding both q and blkcg locks. As blkcg lock
1100-
* is nested inside q lock, this function performs reverse double lock dancing.
1101-
*/
1102-
static void blkcg_destroy_all_blkgs(struct blkcg *blkcg)
1103-
{
1104-
spin_lock_irq(&blkcg->lock);
11051062
while (!hlist_empty(&blkcg->blkg_list)) {
11061063
struct blkcg_gq *blkg = hlist_entry(blkcg->blkg_list.first,
1107-
struct blkcg_gq,
1108-
blkcg_node);
1064+
struct blkcg_gq, blkcg_node);
11091065
struct request_queue *q = blkg->q;
11101066

11111067
if (spin_trylock(q->queue_lock)) {
@@ -1117,16 +1073,17 @@ static void blkcg_destroy_all_blkgs(struct blkcg *blkcg)
11171073
spin_lock_irq(&blkcg->lock);
11181074
}
11191075
}
1076+
11201077
spin_unlock_irq(&blkcg->lock);
1078+
1079+
wb_blkcg_offline(blkcg);
11211080
}
11221081

11231082
static void blkcg_css_free(struct cgroup_subsys_state *css)
11241083
{
11251084
struct blkcg *blkcg = css_to_blkcg(css);
11261085
int i;
11271086

1128-
blkcg_destroy_all_blkgs(blkcg);
1129-
11301087
mutex_lock(&blkcg_pol_mutex);
11311088

11321089
list_del(&blkcg->all_blkcgs_node);
@@ -1480,11 +1437,8 @@ void blkcg_deactivate_policy(struct request_queue *q,
14801437

14811438
list_for_each_entry(blkg, &q->blkg_list, q_node) {
14821439
if (blkg->pd[pol->plid]) {
1483-
if (!blkg->pd[pol->plid]->offline &&
1484-
pol->pd_offline_fn) {
1440+
if (pol->pd_offline_fn)
14851441
pol->pd_offline_fn(blkg->pd[pol->plid]);
1486-
blkg->pd[pol->plid]->offline = true;
1487-
}
14881442
pol->pd_free_fn(blkg->pd[pol->plid]);
14891443
blkg->pd[pol->plid] = NULL;
14901444
}

include/linux/blk-cgroup.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,6 @@ struct blkg_policy_data {
8989
/* the blkg and policy id this per-policy data belongs to */
9090
struct blkcg_gq *blkg;
9191
int plid;
92-
bool offline;
9392
};
9493

9594
/*

0 commit comments

Comments
 (0)