Skip to content

Commit 3154d64

Browse files
YuKuai-huaweigregkh
authored andcommitted
blk-cgroup: support to track if policy is online
commit dfd6200a095440b663099d8d42f1efb0175a1ce3 upstream. A new field 'online' is added to blkg_policy_data to fix following 2 problem: 1) In blkcg_activate_policy(), if pd_alloc_fn() with 'GFP_NOWAIT' failed, 'queue_lock' will be dropped and pd_alloc_fn() will try again without 'GFP_NOWAIT'. In the meantime, remove cgroup can race with it, and pd_offline_fn() will be called without pd_init_fn() and pd_online_fn(). This way null-ptr-deference can be triggered. 2) In order to synchronize pd_free_fn() from blkg_free_workfn() and blkcg_deactivate_policy(), 'list_del_init(&blkg->q_node)' will be delayed to blkg_free_workfn(), hence pd_offline_fn() can be called first in blkg_destroy(), and then blkcg_deactivate_policy() will call it again, we must prevent it. The new field 'online' will be set after pd_online_fn() and will be cleared after pd_offline_fn(), in the meantime pd_offline_fn() will only be called if 'online' is set. Signed-off-by: Yu Kuai <[email protected]> Acked-by: Tejun Heo <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jens Axboe <[email protected]> Signed-off-by: Bin Lan <[email protected]> Signed-off-by: He Zhe <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent d9a807f commit 3154d64

File tree

2 files changed

+18
-7
lines changed

2 files changed

+18
-7
lines changed

block/blk-cgroup.c

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,7 @@ static struct blkcg_gq *blkg_alloc(struct blkcg *blkcg, struct gendisk *disk,
255255
blkg->pd[i] = pd;
256256
pd->blkg = blkg;
257257
pd->plid = i;
258+
pd->online = false;
258259
}
259260

260261
return blkg;
@@ -326,8 +327,11 @@ static struct blkcg_gq *blkg_create(struct blkcg *blkcg, struct gendisk *disk,
326327
for (i = 0; i < BLKCG_MAX_POLS; i++) {
327328
struct blkcg_policy *pol = blkcg_policy[i];
328329

329-
if (blkg->pd[i] && pol->pd_online_fn)
330-
pol->pd_online_fn(blkg->pd[i]);
330+
if (blkg->pd[i]) {
331+
if (pol->pd_online_fn)
332+
pol->pd_online_fn(blkg->pd[i]);
333+
blkg->pd[i]->online = true;
334+
}
331335
}
332336
}
333337
blkg->online = true;
@@ -432,8 +436,11 @@ static void blkg_destroy(struct blkcg_gq *blkg)
432436
for (i = 0; i < BLKCG_MAX_POLS; i++) {
433437
struct blkcg_policy *pol = blkcg_policy[i];
434438

435-
if (blkg->pd[i] && pol->pd_offline_fn)
436-
pol->pd_offline_fn(blkg->pd[i]);
439+
if (blkg->pd[i] && blkg->pd[i]->online) {
440+
if (pol->pd_offline_fn)
441+
pol->pd_offline_fn(blkg->pd[i]);
442+
blkg->pd[i]->online = false;
443+
}
437444
}
438445

439446
blkg->online = false;
@@ -1422,16 +1429,19 @@ int blkcg_activate_policy(struct request_queue *q,
14221429
blkg->pd[pol->plid] = pd;
14231430
pd->blkg = blkg;
14241431
pd->plid = pol->plid;
1432+
pd->online = false;
14251433
}
14261434

14271435
/* all allocated, init in the same order */
14281436
if (pol->pd_init_fn)
14291437
list_for_each_entry_reverse(blkg, &q->blkg_list, q_node)
14301438
pol->pd_init_fn(blkg->pd[pol->plid]);
14311439

1432-
if (pol->pd_online_fn)
1433-
list_for_each_entry_reverse(blkg, &q->blkg_list, q_node)
1440+
list_for_each_entry_reverse(blkg, &q->blkg_list, q_node) {
1441+
if (pol->pd_online_fn)
14341442
pol->pd_online_fn(blkg->pd[pol->plid]);
1443+
blkg->pd[pol->plid]->online = true;
1444+
}
14351445

14361446
__set_bit(pol->plid, q->blkcg_pols);
14371447
ret = 0;
@@ -1493,7 +1503,7 @@ void blkcg_deactivate_policy(struct request_queue *q,
14931503

14941504
spin_lock(&blkcg->lock);
14951505
if (blkg->pd[pol->plid]) {
1496-
if (pol->pd_offline_fn)
1506+
if (blkg->pd[pol->plid]->online && pol->pd_offline_fn)
14971507
pol->pd_offline_fn(blkg->pd[pol->plid]);
14981508
pol->pd_free_fn(blkg->pd[pol->plid]);
14991509
blkg->pd[pol->plid] = NULL;

block/blk-cgroup.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ struct blkg_policy_data {
125125
/* the blkg and policy id this per-policy data belongs to */
126126
struct blkcg_gq *blkg;
127127
int plid;
128+
bool online;
128129
};
129130

130131
/*

0 commit comments

Comments
 (0)