| From 79dfd0a06a59295a9e093f0c7b5ffeb9d55d4908 Mon Sep 17 00:00:00 2001 |
| From: Tejun Heo <tj@kernel.org> |
| Date: Tue, 5 Nov 2019 08:09:51 -0800 |
| Subject: [PATCH] blkcg: make blkcg_print_stat() print stats only for online |
| blkgs |
| |
| commit b0814361a25cba73a224548843ed92d8ea78715a upstream. |
| |
| 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 <tj@kernel.org> |
| Reported-by: Roman Gushchin <guro@fb.com> |
| Cc: Josef Bacik <jbacik@fb.com> |
| Fixes: 903d23f0a354 ("blk-cgroup: allow controllers to output their own stats") |
| Cc: stable@vger.kernel.org # v4.19+ |
| Signed-off-by: Jens Axboe <axboe@kernel.dk> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c |
| index e4715b35d42c..a28865838233 100644 |
| --- a/block/blk-cgroup.c |
| +++ b/block/blk-cgroup.c |
| @@ -945,9 +945,14 @@ static int blkcg_print_stat(struct seq_file *sf, void *v) |
| int i; |
| bool has_stats = false; |
| |
| + spin_lock_irq(&blkg->q->queue_lock); |
| + |
| + if (!blkg->online) |
| + goto skip; |
| + |
| dname = blkg_dev_name(blkg); |
| if (!dname) |
| - continue; |
| + goto skip; |
| |
| /* |
| * Hooray string manipulation, count is the size written NOT |
| @@ -957,8 +962,6 @@ static int blkcg_print_stat(struct seq_file *sf, void *v) |
| */ |
| off += scnprintf(buf+off, size-off, "%s ", dname); |
| |
| - spin_lock_irq(&blkg->q->queue_lock); |
| - |
| rwstat = blkg_rwstat_recursive_sum(blkg, NULL, |
| offsetof(struct blkcg_gq, stat_bytes)); |
| rbytes = atomic64_read(&rwstat.aux_cnt[BLKG_RWSTAT_READ]); |
| @@ -971,8 +974,6 @@ static int blkcg_print_stat(struct seq_file *sf, void *v) |
| wios = atomic64_read(&rwstat.aux_cnt[BLKG_RWSTAT_WRITE]); |
| dios = atomic64_read(&rwstat.aux_cnt[BLKG_RWSTAT_DISCARD]); |
| |
| - spin_unlock_irq(&blkg->q->queue_lock); |
| - |
| if (rbytes || wbytes || rios || wios) { |
| has_stats = true; |
| off += scnprintf(buf+off, size-off, |
| @@ -1013,6 +1014,8 @@ static int blkcg_print_stat(struct seq_file *sf, void *v) |
| seq_commit(sf, -1); |
| } |
| } |
| + skip: |
| + spin_unlock_irq(&blkg->q->queue_lock); |
| } |
| |
| rcu_read_unlock(); |
| -- |
| 2.7.4 |
| |