Skip to content

Commit b081436

Browse files
htejunaxboe
authored andcommitted
blkcg: make blkcg_print_stat() print stats only for online blkgs
blkcg_print_stat() iterates blkgs under RCU and doesn't test whether the blkg is online. This can call into pd_stat_fn() on a pd which is still being initialized leading to an oops. The heaviest operation - recursively summing up rwstat counters - is already done while holding the queue_lock. Expand queue_lock to cover the other operations and skip the blkg if it isn't online yet. The online state is protected by both blkcg and queue locks, so this guarantees that only online blkgs are processed. Signed-off-by: Tejun Heo <[email protected]> Reported-by: Roman Gushchin <[email protected]> Cc: Josef Bacik <[email protected]> Fixes: 903d23f ("blk-cgroup: allow controllers to output their own stats") Cc: [email protected] # v4.19+ Signed-off-by: Jens Axboe <[email protected]>
1 parent 0473976 commit b081436

File tree

1 file changed

+8
-5
lines changed

1 file changed

+8
-5
lines changed

block/blk-cgroup.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -934,9 +934,14 @@ static int blkcg_print_stat(struct seq_file *sf, void *v)
934934
int i;
935935
bool has_stats = false;
936936

937+
spin_lock_irq(&blkg->q->queue_lock);
938+
939+
if (!blkg->online)
940+
goto skip;
941+
937942
dname = blkg_dev_name(blkg);
938943
if (!dname)
939-
continue;
944+
goto skip;
940945

941946
/*
942947
* Hooray string manipulation, count is the size written NOT
@@ -946,8 +951,6 @@ static int blkcg_print_stat(struct seq_file *sf, void *v)
946951
*/
947952
off += scnprintf(buf+off, size-off, "%s ", dname);
948953

949-
spin_lock_irq(&blkg->q->queue_lock);
950-
951954
blkg_rwstat_recursive_sum(blkg, NULL,
952955
offsetof(struct blkcg_gq, stat_bytes), &rwstat);
953956
rbytes = rwstat.cnt[BLKG_RWSTAT_READ];
@@ -960,8 +963,6 @@ static int blkcg_print_stat(struct seq_file *sf, void *v)
960963
wios = rwstat.cnt[BLKG_RWSTAT_WRITE];
961964
dios = rwstat.cnt[BLKG_RWSTAT_DISCARD];
962965

963-
spin_unlock_irq(&blkg->q->queue_lock);
964-
965966
if (rbytes || wbytes || rios || wios) {
966967
has_stats = true;
967968
off += scnprintf(buf+off, size-off,
@@ -999,6 +1000,8 @@ static int blkcg_print_stat(struct seq_file *sf, void *v)
9991000
seq_commit(sf, -1);
10001001
}
10011002
}
1003+
skip:
1004+
spin_unlock_irq(&blkg->q->queue_lock);
10021005
}
10031006

10041007
rcu_read_unlock();

0 commit comments

Comments
 (0)