Commit 252c651a authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Jens Axboe

blk-cgroup: stop using seq_get_buf

seq_get_buf is a crutch that undoes all the memory safety of the
seq_file interface.  Use the normal seq_printf interfaces instead.
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Acked-by: default avatarTejun Heo <tj@kernel.org>
Link: https://lore.kernel.org/r/20210810152623.1796144-2-hch@lst.deSigned-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 49cb5168
...@@ -877,8 +877,6 @@ static void blkcg_print_one_stat(struct blkcg_gq *blkg, struct seq_file *s) ...@@ -877,8 +877,6 @@ static void blkcg_print_one_stat(struct blkcg_gq *blkg, struct seq_file *s)
bool has_stats = false; bool has_stats = false;
const char *dname; const char *dname;
unsigned seq; unsigned seq;
char *buf;
size_t size = seq_get_buf(s, &buf), off = 0;
int i; int i;
if (!blkg->online) if (!blkg->online)
...@@ -888,13 +886,7 @@ static void blkcg_print_one_stat(struct blkcg_gq *blkg, struct seq_file *s) ...@@ -888,13 +886,7 @@ static void blkcg_print_one_stat(struct blkcg_gq *blkg, struct seq_file *s)
if (!dname) if (!dname)
return; return;
/* seq_printf(s, "%s ", dname);
* Hooray string manipulation, count is the size written NOT
* INCLUDING THE \0, so size is now count+1 less than what we
* had before, but we want to start writing the next bit from
* the \0 so we only add count to buf.
*/
off += scnprintf(buf+off, size-off, "%s ", dname);
do { do {
seq = u64_stats_fetch_begin(&bis->sync); seq = u64_stats_fetch_begin(&bis->sync);
...@@ -909,40 +901,30 @@ static void blkcg_print_one_stat(struct blkcg_gq *blkg, struct seq_file *s) ...@@ -909,40 +901,30 @@ static void blkcg_print_one_stat(struct blkcg_gq *blkg, struct seq_file *s)
if (rbytes || wbytes || rios || wios) { if (rbytes || wbytes || rios || wios) {
has_stats = true; has_stats = true;
off += scnprintf(buf+off, size-off, seq_printf(s, "rbytes=%llu wbytes=%llu rios=%llu wios=%llu dbytes=%llu dios=%llu",
"rbytes=%llu wbytes=%llu rios=%llu wios=%llu dbytes=%llu dios=%llu",
rbytes, wbytes, rios, wios, rbytes, wbytes, rios, wios,
dbytes, dios); dbytes, dios);
} }
if (blkcg_debug_stats && atomic_read(&blkg->use_delay)) { if (blkcg_debug_stats && atomic_read(&blkg->use_delay)) {
has_stats = true; has_stats = true;
off += scnprintf(buf+off, size-off, " use_delay=%d delay_nsec=%llu", seq_printf(s, " use_delay=%d delay_nsec=%llu",
atomic_read(&blkg->use_delay), atomic_read(&blkg->use_delay),
atomic64_read(&blkg->delay_nsec)); atomic64_read(&blkg->delay_nsec));
} }
for (i = 0; i < BLKCG_MAX_POLS; i++) { for (i = 0; i < BLKCG_MAX_POLS; i++) {
struct blkcg_policy *pol = blkcg_policy[i]; struct blkcg_policy *pol = blkcg_policy[i];
size_t written;
if (!blkg->pd[i] || !pol->pd_stat_fn) if (!blkg->pd[i] || !pol->pd_stat_fn)
continue; continue;
written = pol->pd_stat_fn(blkg->pd[i], buf+off, size-off); if (pol->pd_stat_fn(blkg->pd[i], s))
if (written)
has_stats = true; has_stats = true;
off += written;
} }
if (has_stats) { if (has_stats)
if (off < size - 1) { seq_printf(s, "\n");
off += scnprintf(buf+off, size-off, "\n");
seq_commit(s, off);
} else {
seq_commit(s, -1);
}
}
} }
static int blkcg_print_stat(struct seq_file *sf, void *v) static int blkcg_print_stat(struct seq_file *sf, void *v)
......
...@@ -2988,34 +2988,29 @@ static void ioc_pd_free(struct blkg_policy_data *pd) ...@@ -2988,34 +2988,29 @@ static void ioc_pd_free(struct blkg_policy_data *pd)
kfree(iocg); kfree(iocg);
} }
static size_t ioc_pd_stat(struct blkg_policy_data *pd, char *buf, size_t size) static bool ioc_pd_stat(struct blkg_policy_data *pd, struct seq_file *s)
{ {
struct ioc_gq *iocg = pd_to_iocg(pd); struct ioc_gq *iocg = pd_to_iocg(pd);
struct ioc *ioc = iocg->ioc; struct ioc *ioc = iocg->ioc;
size_t pos = 0;
if (!ioc->enabled) if (!ioc->enabled)
return 0; return false;
if (iocg->level == 0) { if (iocg->level == 0) {
unsigned vp10k = DIV64_U64_ROUND_CLOSEST( unsigned vp10k = DIV64_U64_ROUND_CLOSEST(
ioc->vtime_base_rate * 10000, ioc->vtime_base_rate * 10000,
VTIME_PER_USEC); VTIME_PER_USEC);
pos += scnprintf(buf + pos, size - pos, " cost.vrate=%u.%02u", seq_printf(s, " cost.vrate=%u.%02u", vp10k / 100, vp10k % 100);
vp10k / 100, vp10k % 100);
} }
pos += scnprintf(buf + pos, size - pos, " cost.usage=%llu", seq_printf(s, " cost.usage=%llu", iocg->last_stat.usage_us);
iocg->last_stat.usage_us);
if (blkcg_debug_stats) if (blkcg_debug_stats)
pos += scnprintf(buf + pos, size - pos, seq_printf(s, " cost.wait=%llu cost.indebt=%llu cost.indelay=%llu",
" cost.wait=%llu cost.indebt=%llu cost.indelay=%llu", iocg->last_stat.wait_us,
iocg->last_stat.wait_us, iocg->last_stat.indebt_us,
iocg->last_stat.indebt_us, iocg->last_stat.indelay_us);
iocg->last_stat.indelay_us); return true;
return pos;
} }
static u64 ioc_weight_prfill(struct seq_file *sf, struct blkg_policy_data *pd, static u64 ioc_weight_prfill(struct seq_file *sf, struct blkg_policy_data *pd,
......
...@@ -886,8 +886,7 @@ static int iolatency_print_limit(struct seq_file *sf, void *v) ...@@ -886,8 +886,7 @@ static int iolatency_print_limit(struct seq_file *sf, void *v)
return 0; return 0;
} }
static size_t iolatency_ssd_stat(struct iolatency_grp *iolat, char *buf, static bool iolatency_ssd_stat(struct iolatency_grp *iolat, struct seq_file *s)
size_t size)
{ {
struct latency_stat stat; struct latency_stat stat;
int cpu; int cpu;
...@@ -902,39 +901,40 @@ static size_t iolatency_ssd_stat(struct iolatency_grp *iolat, char *buf, ...@@ -902,39 +901,40 @@ static size_t iolatency_ssd_stat(struct iolatency_grp *iolat, char *buf,
preempt_enable(); preempt_enable();
if (iolat->rq_depth.max_depth == UINT_MAX) if (iolat->rq_depth.max_depth == UINT_MAX)
return scnprintf(buf, size, " missed=%llu total=%llu depth=max", seq_printf(s, " missed=%llu total=%llu depth=max",
(unsigned long long)stat.ps.missed, (unsigned long long)stat.ps.missed,
(unsigned long long)stat.ps.total); (unsigned long long)stat.ps.total);
return scnprintf(buf, size, " missed=%llu total=%llu depth=%u", else
(unsigned long long)stat.ps.missed, seq_printf(s, " missed=%llu total=%llu depth=%u",
(unsigned long long)stat.ps.total, (unsigned long long)stat.ps.missed,
iolat->rq_depth.max_depth); (unsigned long long)stat.ps.total,
iolat->rq_depth.max_depth);
return true;
} }
static size_t iolatency_pd_stat(struct blkg_policy_data *pd, char *buf, static bool iolatency_pd_stat(struct blkg_policy_data *pd, struct seq_file *s)
size_t size)
{ {
struct iolatency_grp *iolat = pd_to_lat(pd); struct iolatency_grp *iolat = pd_to_lat(pd);
unsigned long long avg_lat; unsigned long long avg_lat;
unsigned long long cur_win; unsigned long long cur_win;
if (!blkcg_debug_stats) if (!blkcg_debug_stats)
return 0; return false;
if (iolat->ssd) if (iolat->ssd)
return iolatency_ssd_stat(iolat, buf, size); return iolatency_ssd_stat(iolat, s);
avg_lat = div64_u64(iolat->lat_avg, NSEC_PER_USEC); avg_lat = div64_u64(iolat->lat_avg, NSEC_PER_USEC);
cur_win = div64_u64(iolat->cur_win_nsec, NSEC_PER_MSEC); cur_win = div64_u64(iolat->cur_win_nsec, NSEC_PER_MSEC);
if (iolat->rq_depth.max_depth == UINT_MAX) if (iolat->rq_depth.max_depth == UINT_MAX)
return scnprintf(buf, size, " depth=max avg_lat=%llu win=%llu", seq_printf(s, " depth=max avg_lat=%llu win=%llu",
avg_lat, cur_win); avg_lat, cur_win);
else
return scnprintf(buf, size, " depth=%u avg_lat=%llu win=%llu", seq_printf(s, " depth=%u avg_lat=%llu win=%llu",
iolat->rq_depth.max_depth, avg_lat, cur_win); iolat->rq_depth.max_depth, avg_lat, cur_win);
return true;
} }
static struct blkg_policy_data *iolatency_pd_alloc(gfp_t gfp, static struct blkg_policy_data *iolatency_pd_alloc(gfp_t gfp,
struct request_queue *q, struct request_queue *q,
struct blkcg *blkcg) struct blkcg *blkcg)
......
...@@ -52,7 +52,7 @@ struct dd_blkcg *dd_blkcg_from_bio(struct bio *bio) ...@@ -52,7 +52,7 @@ struct dd_blkcg *dd_blkcg_from_bio(struct bio *bio)
return dd_blkcg_from_pd(pd); return dd_blkcg_from_pd(pd);
} }
static size_t dd_pd_stat(struct blkg_policy_data *pd, char *buf, size_t size) static bool dd_pd_stat(struct blkg_policy_data *pd, struct seq_file *s)
{ {
static const char *const prio_class_name[] = { static const char *const prio_class_name[] = {
[IOPRIO_CLASS_NONE] = "NONE", [IOPRIO_CLASS_NONE] = "NONE",
...@@ -61,12 +61,10 @@ static size_t dd_pd_stat(struct blkg_policy_data *pd, char *buf, size_t size) ...@@ -61,12 +61,10 @@ static size_t dd_pd_stat(struct blkg_policy_data *pd, char *buf, size_t size)
[IOPRIO_CLASS_IDLE] = "IDLE", [IOPRIO_CLASS_IDLE] = "IDLE",
}; };
struct dd_blkcg *blkcg = dd_blkcg_from_pd(pd); struct dd_blkcg *blkcg = dd_blkcg_from_pd(pd);
int res = 0;
u8 prio; u8 prio;
for (prio = 0; prio < ARRAY_SIZE(blkcg->stats->stats); prio++) for (prio = 0; prio < ARRAY_SIZE(blkcg->stats->stats); prio++)
res += scnprintf(buf + res, size - res, seq_printf(s, " [%s] dispatched=%u inserted=%u merged=%u",
" [%s] dispatched=%u inserted=%u merged=%u",
prio_class_name[prio], prio_class_name[prio],
ddcg_sum(blkcg, dispatched, prio) + ddcg_sum(blkcg, dispatched, prio) +
ddcg_sum(blkcg, merged, prio) - ddcg_sum(blkcg, merged, prio) -
...@@ -75,7 +73,7 @@ static size_t dd_pd_stat(struct blkg_policy_data *pd, char *buf, size_t size) ...@@ -75,7 +73,7 @@ static size_t dd_pd_stat(struct blkg_policy_data *pd, char *buf, size_t size)
ddcg_sum(blkcg, completed, prio), ddcg_sum(blkcg, completed, prio),
ddcg_sum(blkcg, merged, prio)); ddcg_sum(blkcg, merged, prio));
return res; return true;
} }
static struct blkg_policy_data *dd_pd_alloc(gfp_t gfp, struct request_queue *q, static struct blkg_policy_data *dd_pd_alloc(gfp_t gfp, struct request_queue *q,
......
...@@ -152,8 +152,8 @@ typedef void (blkcg_pol_online_pd_fn)(struct blkg_policy_data *pd); ...@@ -152,8 +152,8 @@ typedef void (blkcg_pol_online_pd_fn)(struct blkg_policy_data *pd);
typedef void (blkcg_pol_offline_pd_fn)(struct blkg_policy_data *pd); typedef void (blkcg_pol_offline_pd_fn)(struct blkg_policy_data *pd);
typedef void (blkcg_pol_free_pd_fn)(struct blkg_policy_data *pd); typedef void (blkcg_pol_free_pd_fn)(struct blkg_policy_data *pd);
typedef void (blkcg_pol_reset_pd_stats_fn)(struct blkg_policy_data *pd); typedef void (blkcg_pol_reset_pd_stats_fn)(struct blkg_policy_data *pd);
typedef size_t (blkcg_pol_stat_pd_fn)(struct blkg_policy_data *pd, char *buf, typedef bool (blkcg_pol_stat_pd_fn)(struct blkg_policy_data *pd,
size_t size); struct seq_file *s);
struct blkcg_policy { struct blkcg_policy {
int plid; int plid;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment