Skip to content

Commit dfd6200

Browse files
YuKuai-huaweiaxboe
authored andcommitted
blk-cgroup: support to track if policy is online
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 <yukuai3@huawei.com> Acked-by: Tejun Heo <tj@kernel.org> Reviewed-by: Christoph Hellwig <hch@lst.de> Link: https://lore.kernel.org/r/20230119110350.2287325-3-yukuai1@huaweicloud.com Signed-off-by: Jens Axboe <axboe@kernel.dk>
1 parent c7241ba commit dfd6200

2 files changed

Lines changed: 18 additions & 7 deletions

File tree

block/blk-cgroup.c

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,7 @@ static struct blkcg_gq *blkg_alloc(struct blkcg *blkcg, struct gendisk *disk,
288288
blkg->pd[i] = pd;
289289
pd->blkg = blkg;
290290
pd->plid = i;
291+
pd->online = false;
291292
}
292293

293294
return blkg;
@@ -359,8 +360,11 @@ static struct blkcg_gq *blkg_create(struct blkcg *blkcg, struct gendisk *disk,
359360
for (i = 0; i < BLKCG_MAX_POLS; i++) {
360361
struct blkcg_policy *pol = blkcg_policy[i];
361362

362-
if (blkg->pd[i] && pol->pd_online_fn)
363-
pol->pd_online_fn(blkg->pd[i]);
363+
if (blkg->pd[i]) {
364+
if (pol->pd_online_fn)
365+
pol->pd_online_fn(blkg->pd[i]);
366+
blkg->pd[i]->online = true;
367+
}
364368
}
365369
}
366370
blkg->online = true;
@@ -465,8 +469,11 @@ static void blkg_destroy(struct blkcg_gq *blkg)
465469
for (i = 0; i < BLKCG_MAX_POLS; i++) {
466470
struct blkcg_policy *pol = blkcg_policy[i];
467471

468-
if (blkg->pd[i] && pol->pd_offline_fn)
469-
pol->pd_offline_fn(blkg->pd[i]);
472+
if (blkg->pd[i] && blkg->pd[i]->online) {
473+
if (pol->pd_offline_fn)
474+
pol->pd_offline_fn(blkg->pd[i]);
475+
blkg->pd[i]->online = false;
476+
}
470477
}
471478

472479
blkg->online = false;
@@ -1448,16 +1455,19 @@ int blkcg_activate_policy(struct request_queue *q,
14481455
blkg->pd[pol->plid] = pd;
14491456
pd->blkg = blkg;
14501457
pd->plid = pol->plid;
1458+
pd->online = false;
14511459
}
14521460

14531461
/* all allocated, init in the same order */
14541462
if (pol->pd_init_fn)
14551463
list_for_each_entry_reverse(blkg, &q->blkg_list, q_node)
14561464
pol->pd_init_fn(blkg->pd[pol->plid]);
14571465

1458-
if (pol->pd_online_fn)
1459-
list_for_each_entry_reverse(blkg, &q->blkg_list, q_node)
1466+
list_for_each_entry_reverse(blkg, &q->blkg_list, q_node) {
1467+
if (pol->pd_online_fn)
14601468
pol->pd_online_fn(blkg->pd[pol->plid]);
1469+
blkg->pd[pol->plid]->online = true;
1470+
}
14611471

14621472
__set_bit(pol->plid, q->blkcg_pols);
14631473
ret = 0;
@@ -1519,7 +1529,7 @@ void blkcg_deactivate_policy(struct request_queue *q,
15191529

15201530
spin_lock(&blkcg->lock);
15211531
if (blkg->pd[pol->plid]) {
1522-
if (pol->pd_offline_fn)
1532+
if (blkg->pd[pol->plid]->online && pol->pd_offline_fn)
15231533
pol->pd_offline_fn(blkg->pd[pol->plid]);
15241534
pol->pd_free_fn(blkg->pd[pol->plid]);
15251535
blkg->pd[pol->plid] = NULL;

block/blk-cgroup.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ struct blkg_policy_data {
135135
/* the blkg and policy id this per-policy data belongs to */
136136
struct blkcg_gq *blkg;
137137
int plid;
138+
bool online;
138139
};
139140

140141
/*

0 commit comments

Comments
 (0)