Skip to content

Commit

Permalink
blkcg: make blkcg_print_stat() print stats only for online blkgs
Browse files Browse the repository at this point in the history
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: 903d23f ("blk-cgroup: allow controllers to output their own stats")
Cc: stable@vger.kernel.org # v4.19+
Signed-off-by: Jens Axboe <axboe@kernel.dk>
  • Loading branch information
Tejun Heo authored and Jens Axboe committed Nov 7, 2019
1 parent 0473976 commit b081436
Showing 1 changed file with 8 additions and 5 deletions.
13 changes: 8 additions & 5 deletions block/blk-cgroup.c
Original file line number Diff line number Diff line change
Expand Up @@ -934,9 +934,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
Expand All @@ -946,8 +951,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);

blkg_rwstat_recursive_sum(blkg, NULL,
offsetof(struct blkcg_gq, stat_bytes), &rwstat);
rbytes = rwstat.cnt[BLKG_RWSTAT_READ];
Expand All @@ -960,8 +963,6 @@ static int blkcg_print_stat(struct seq_file *sf, void *v)
wios = rwstat.cnt[BLKG_RWSTAT_WRITE];
dios = rwstat.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,
Expand Down Expand Up @@ -999,6 +1000,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();
Expand Down

0 comments on commit b081436

Please sign in to comment.