mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-01 10:43:43 +00:00
blk-cgroup: prevent rcu_sched detected stalls warnings while iterating blkgs
We run a test that create millions of cgroups and blkgs, and then trigger blkg_destroy_all(). blkg_destroy_all() will hold spin lock for a long time in such situation. Thus release the lock when a batch of blkgs are destroyed. blkcg_activate_policy() and blkcg_deactivate_policy() might have the same problem, however, as they are basically only called from module init/exit paths, let's leave them alone for now. Signed-off-by: Yu Kuai <yukuai3@huawei.com> Acked-by: Tejun Heo <tj@kernel.org> Link: https://lore.kernel.org/r/20210707015649.1929797-1-yukuai3@huawei.com Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
parent
d80c228d44
commit
a731763fc4
@ -56,6 +56,8 @@ static LIST_HEAD(all_blkcgs); /* protected by blkcg_pol_mutex */
|
|||||||
bool blkcg_debug_stats = false;
|
bool blkcg_debug_stats = false;
|
||||||
static struct workqueue_struct *blkcg_punt_bio_wq;
|
static struct workqueue_struct *blkcg_punt_bio_wq;
|
||||||
|
|
||||||
|
#define BLKG_DESTROY_BATCH_SIZE 64
|
||||||
|
|
||||||
static bool blkcg_policy_enabled(struct request_queue *q,
|
static bool blkcg_policy_enabled(struct request_queue *q,
|
||||||
const struct blkcg_policy *pol)
|
const struct blkcg_policy *pol)
|
||||||
{
|
{
|
||||||
@ -422,7 +424,9 @@ static void blkg_destroy(struct blkcg_gq *blkg)
|
|||||||
static void blkg_destroy_all(struct request_queue *q)
|
static void blkg_destroy_all(struct request_queue *q)
|
||||||
{
|
{
|
||||||
struct blkcg_gq *blkg, *n;
|
struct blkcg_gq *blkg, *n;
|
||||||
|
int count = BLKG_DESTROY_BATCH_SIZE;
|
||||||
|
|
||||||
|
restart:
|
||||||
spin_lock_irq(&q->queue_lock);
|
spin_lock_irq(&q->queue_lock);
|
||||||
list_for_each_entry_safe(blkg, n, &q->blkg_list, q_node) {
|
list_for_each_entry_safe(blkg, n, &q->blkg_list, q_node) {
|
||||||
struct blkcg *blkcg = blkg->blkcg;
|
struct blkcg *blkcg = blkg->blkcg;
|
||||||
@ -430,6 +434,17 @@ static void blkg_destroy_all(struct request_queue *q)
|
|||||||
spin_lock(&blkcg->lock);
|
spin_lock(&blkcg->lock);
|
||||||
blkg_destroy(blkg);
|
blkg_destroy(blkg);
|
||||||
spin_unlock(&blkcg->lock);
|
spin_unlock(&blkcg->lock);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* in order to avoid holding the spin lock for too long, release
|
||||||
|
* it when a batch of blkgs are destroyed.
|
||||||
|
*/
|
||||||
|
if (!(--count)) {
|
||||||
|
count = BLKG_DESTROY_BATCH_SIZE;
|
||||||
|
spin_unlock_irq(&q->queue_lock);
|
||||||
|
cond_resched();
|
||||||
|
goto restart;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
q->root_blkg = NULL;
|
q->root_blkg = NULL;
|
||||||
|
Loading…
Reference in New Issue
Block a user