blkcg: blkcg stats cleanup
Subsystems (4)
Tejun Heo
maintainerPATCH v2 1/1 blkcg: blkcg stats cleanup
Hello,
This is v2 of blkcg stats cleanup patchset. Changes from the last take[L] are
* The following patches added to consolidate blkcg entry point and blkg creation. This is in itself is an improvement and helps colllecting common stats on bio issue.
0002-blkcg-inline-__-blkg_lookup.patch 0003-blkcg-move-root-blkg-lookup-optimization-from-throtl.patch 0004-blk-throttle-improve-queue-bypass-handling.patch 0005-blkcg-consolidate-blkg-creation-in-blkcg_bio_issue_c.patch
* per-blkg stats now accounted on bio issue rather than request completion so that bio based and request based drivers can behave the same way. The issue was spotted by Vivek.
blkcg's stats have always been somwhat of a mess. This patchset tries to improve the situation a bit.
* cfq-iosched implements custom recursive stats and blk-throttle implements custom per-cpu stats. This patchset make blkcg core support both by default.
* cfq-iosched and blk-throttle keep track of the same stats multiple times. Unify them.
This patchset contains the following ten patches.
0001-cgroup-make-cftype-private-a-unsigned-long.patch 0002-blkcg-inline-__-blkg_lookup.patch 0003-blkcg-move-root-blkg-lookup-optimization-from-throtl.patch 0004-blk-throttle-improve-queue-bypass-handling.patch 0005-blkcg-consolidate-blkg-creation-in-blkcg_bio_issue_c.patch 0006-blkcg-add-blkg_-rw-stat-aux_cnt-and-replace-cfq_grou.patch 0007-blkcg-make-blkcg_-rw-stat-per-cpu.patch 0008-blkcg-make-blkg_-rw-stat_recursive_sum-to-be-able-to.patch 0009-blkcg-move-io_service_bytes-and-io_serviced-stats-in.patch 0010-blkcg-remove-cfqg_stats-sectors.patch
0001-0005 are prep patches. 0006-0008 make blkg stats per-cpu. 0009-0010 consolidate common stats across policies.
This patchset is also available in the following git branch.
git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup.git review-blkcg-stats-cleanup
and is on top of
block/for-linus 06b285bd1125 ("blkcg: fix blkcg_policy_data allocation bug")
+ [1] [PATCHSET block/for-4.3] writeback: cgroup writeback updates
+ [2] [PATCHSET v2 block/for-4.3] block, cgroup: make cfq charge async IOs to the appropriate blkcgs
+ [3] [PATCHSET v3 block/for-4.3] blkcg: blkcg policy methods and data handling cleanup
diffstat follows. Thanks.
block/blk-cgroup.c | 215 +++++++++++++++++++++++++----------- block/blk-core.c | 4 block/blk-throttle.c | 188 ++----------------------------- block/blk.h | 5 block/cfq-iosched.c | 241 ++++++++++++++++++---------------------- include/linux/blk-cgroup.h | 261 ++++++++++++++++++++++++++++++++------------ include/linux/cgroup-defs.h | 2 7 files changed, 471 insertions(+), 445 deletions(-)
--
tejun
[L] http://lkml.kernel.org/g/[email protected]
[1] http://lkml.kernel.org/g/[email protected]
[2] http://lkml.kernel.org/g/[email protected]
[3] http://lkml.kernel.org/g/[email protected]
Tejun Heo
maintainerPATCH 1/10 cgroup: make cftype->private a unsigned long
It's pretty unusual to have an int as a private data field and it makes it impossible to carray a pointer value through it. Let's make it an unsigned long. AFAICS, this shouldn't break anything.
--- include/linux/cgroup-defs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
include/linux/cgroup-defs.h +1 -1
@@ -318,7 +318,7 @@ struct cftype {* end of cftype array. */ char name[MAX_CFTYPE_NAME ]; -int private; +unsigned long private;/* * If not 0, file mode is set to this value, otherwise it will * be figured out automatically
Signature · 1 line
2.4.3
Re: [PATCH 01/10] cgroup: make cftype->private a unsigned long
Quoted 7 lines · Tejun Heo
It's pretty unusual to have an int as a private data field and it makes it impossible to carray a pointer value through it. Let's make it an unsigned long. AFAICS, this shouldn't break anything.
Signed-off-by Tejun Heo <[email protected]>Acked-by Li Zefan <[email protected]>Cc Johannes Weiner <[email protected]>
Applied this one to cgroup/for-4.3-unified-base.
Thanks.
Signature · 1 line
tejun
Tejun Heo
maintainerPATCH 2/10 blkcg: inline [__]blkg_lookup()
In reply to Tejun Heoblkg_lookup() checks whether the target queue is bypassing and, if not, calls __blkg_lookup() which first checks the lookup hint and then performs radix tree walk. The operations upto hint checking are trivial and there are many users of this function. This patch inlines blkg_lookup() and the fast path part of __blkg_lookup(). The radix tree lookup and hint update are now in blkg_lookup_slowpath().
This will help consolidating blkg handling by easing moving root blkcg short-circuit to inlined lookup fast path.
--- block/blk-cgroup.c | 38 ++--------------------------------- include/linux/blk-cgroup.h | 49 ++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 47 insertions(+), 40 deletions(-)
block/blk-cgroup.c +2 -36
@@ -131,26 +131,11 @@ static struct blkcg_gq *blkg_alloc(struct blkcg *blkcg, struct request_queue *q,return NULL ; } -/** -* __blkg_lookup - internal version of blkg_lookup() -* @blkcg: blkcg of interest -* @q: request_queue of interest -* @update_hint: whether to update lookup hint with the result or not -* -* This is internal version and shouldn't be used by policy -* implementations. Looks up blkgs for the @blkcg - @q pair regardless of -* @q's bypass state. If @update_hint is %true, the caller should be -* holding @q->queue_lock and lookup hint is updated on success. -*/ -struct blkcg_gq *__blkg_lookup (struct blkcg *blkcg,struct request_queue *q, -bool update_hint) +struct blkcg_gq *blkg_lookup_slowpath (struct blkcg *blkcg, +struct request_queue *q,bool update_hint) {struct blkcg_gq *blkg; - blkg =rcu_dereference (blkcg->blkg_hint); -if (blkg && blkg->q == q) -return blkg; -/* * Hint didn't match. Look up from the radix tree. Note that the * hint can only be updated under queue_lock as otherwise @blkg
@@ -169,25 +154,6 @@ struct blkcg_gq *__blkg_lookup(struct blkcg *blkcg, struct request_queue *q,return NULL ; } -/** -* blkg_lookup - lookup blkg for the specified blkcg - q pair -* @blkcg: blkcg of interest -* @q: request_queue of interest -* -* Lookup blkg for the @blkcg - @q pair. This function should be called -* under RCU read lock and is guaranteed to return %NULL if @q is bypassing -* - see blk_queue_bypass_start() for details. -*/ -struct blkcg_gq *blkg_lookup (struct blkcg *blkcg,struct request_queue *q) -{ -WARN_ON_ONCE (!rcu_read_lock_held ()); - -if (unlikely (blk_queue_bypass (q))) -return NULL ; -return __blkg_lookup (blkcg, q, false); -} -EXPORT_SYMBOL_GPL (blkg_lookup); -/* * If @new_blkg is %NULL, this function tries to allocate a new one as * necessary using %GFP_NOWAIT. @new_blkg is always consumed on return.
include/linux/blk-cgroup.h +45 -4
67 lines not on this page · raw message
Signature · 1 line
2.4.3
Tejun Heo
maintainerPATCH 3/10 blkcg: move root blkg lookup optimization from throtl_lookup_tg() to __blkg_lookup()
In reply to Tejun HeoCurrently, both throttle and cfq policies implement their own root blkg (blkcg_gq) lookup fast path. This patch moves root blkg optimization from throtl_lookup_tg() to __blkg_lookup(). cfq-iosched currently doesn't use blkg_lookup() but will be converted and drop the optimization too.
--- block/blk-throttle.c | 7 ------- include/linux/blk-cgroup.h | 3 +++ 2 files changed, 3 insertions(+), 7 deletions(-)
block/blk-throttle.c +0 -7
@@ -452,13 +452,6 @@ static void throtl_pd_reset_stats(struct blkg_policy_data *pd)static struct throtl_grp *throtl_lookup_tg (struct throtl_data *td,struct blkcg *blkcg) { -/* -* This is the common case when there are no blkcgs. Avoid lookup -* in this case -*/ -if (blkcg == &blkcg_root) -return td_root_tg (td); -return blkg_to_tg (blkg_lookup (blkcg, td->queue)); }
include/linux/blk-cgroup.h +3 -0
@@ -249,6 +249,9 @@ static inline struct blkcg_gq *__blkg_lookup(struct blkcg *blkcg, {struct blkcg_gq *blkg; +if (blkcg == &blkcg_root) +return q->root_blkg; + blkg =rcu_dereference (blkcg->blkg_hint);if (blkg && blkg->q == q)return blkg;
Signature · 1 line
2.4.3
Tejun Heo
maintainerPATCH 4/10 blk-throttle: improve queue bypass handling
In reply to Tejun HeoIf a queue is bypassing, all blkcg policies should become noops but blk-throttle wasn't. It only became noop if the queue was dying. While this wouldn't lead to an oops as falling back to the root blkg is safe in this case, this can be a bit surprising - a bypassing queue could still be applying throttle limits.
Fix it by removing blk_queue_dying() test in throtl_lookup_create_tg() and testing blk_queue_bypass() in blk_throtl_bio() and bypassing before doing anything else.
--- block/blk-throttle.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
block/blk-throttle.c +4 -3
@@ -475,7 +475,7 @@ static struct throtl_grp *throtl_lookup_create_tg(struct throtl_data *td,/* if %NULL and @q is alive, fall back to root_tg */ if (!IS_ERR (blkg)) tg =blkg_to_tg (blkg); -else if (!blk_queue_dying (q)) +else tg =td_root_tg (td); }
@@ -1438,10 +1438,11 @@ bool blk_throtl_bio(struct request_queue *q, struct bio *bio)* IO group */ spin_lock_irq (q->queue_lock); - tg =throtl_lookup_create_tg (td, blkcg); -if (unlikely (!tg)) + +if (unlikely (blk_queue_bypass (q))) goto out_unlock; + tg =throtl_lookup_create_tg (td, blkcg); sq = &tg->service_queue;while (true) {
Signature · 1 line
2.4.3
Tejun Heo
maintainerPATCH 5/10 blkcg: consolidate blkg creation in blkcg_bio_issue_check()
In reply to Tejun Heoblkg (blkcg_gq) currently is created by blkcg policies invoking blkg_lookup_create() which ends up repeating about the same code in different policies. Theoretically, this can avoid the overhead of looking and/or creating blkg's if blkcg is enabled but no policy is in use; however, the cost of blkg lookup / creation is very low especially if only the root blkcg is in use which is highly likely if no blkcg policy is in active use - it boils down to a single very predictable conditional and surrounding RCU protection.
This patch consolidates blkg creation to a new function blkcg_bio_issue_check() which is called during bio issue from generic_make_request_checks(). blkcg_bio_issue_check() is now the only function which tries to create missing blkg's. The subsequent policy and request_list operations just perform blkg_lookup() and if missing falls back to the root.
* blk_get_rl() no longer tries to create blkg. It uses blkg_lookup() instead of blkg_lookup_create().
* blk_throtl_bio() is now called from blkcg_bio_issue_check() with rcu read locked and blkg already looked up. Both throtl_lookup_tg() and throtl_lookup_create_tg() are dropped.
* cfq is similarly updated. cfq_lookup_create_cfqg() is dropped and cfq_get_queue() now directly uses blkg_lookup() and falls back to oom_cfqg on failure.
This consolidates blkg handling and avoids unnecessary blkg creation retries under memory pressure. In addition, this provides a common bio entry point into blkcg where things like common accounting can be performed.
--- block/blk-cgroup.c | 2 +- block/blk-core.c | 4 +-- block/blk-throttle.c | 72 ++++------------------------------------------ block/blk.h | 5 ---- block/cfq-iosched.c | 37 ++++-------------------- include/linux/blk-cgroup.h | 40 ++++++++++++++++++++++++-- 6 files changed, 52 insertions(+), 108 deletions(-)
block/blk-cgroup.c +1 -1
@@ -153,6 +153,7 @@ struct blkcg_gq *blkg_lookup_slowpath(struct blkcg *blkcg,return NULL ; } +EXPORT_SYMBOL_GPL (blkg_lookup_slowpath);/* * If @new_blkg is %NULL, this function tries to allocate a new one as
@@ -295,7 +296,6 @@ struct blkcg_gq *blkg_lookup_create(struct blkcg *blkcg,return blkg; } } -EXPORT_SYMBOL_GPL (blkg_lookup_create);static void blkg_destroy (struct blkcg_gq *blkg) {
block/blk-core.c +2 -2
@@ -1889,8 +1889,8 @@ generic_make_request_checks(struct bio *bio)*/ create_io_context (GFP_ATOMIC , q->node); -if (blk_throtl_bio (q, bio)) -return false;/* throttled, will be resubmitted later */ +if (!blkcg_bio_issue_check (q, bio)) +return false;trace_block_bio_queue (q, bio);return true;
block/blk-throttle.c +6 -66
110 lines not on this page · raw message
block/blk.h +0 -5
@@ -266,15 +266,10 @@ static inline struct io_context *create_io_context(gfp_t gfp_mask, int node)* Internal throttling interface */ #ifdef CONFIG_BLK_DEV_THROTTLING -extern bool blk_throtl_bio (struct request_queue *q,struct bio *bio);extern void blk_throtl_drain (struct request_queue *q);extern int blk_throtl_init (struct request_queue *q);extern void blk_throtl_exit (struct request_queue *q);#else /* CONFIG_BLK_DEV_THROTTLING */ -static inline bool blk_throtl_bio (struct request_queue *q,struct bio *bio) -{ -return false; -}static inline void blk_throtl_drain (struct request_queue *q) { }static inline int blk_throtl_init (struct request_queue *q) {return 0 ; }static inline void blk_throtl_exit (struct request_queue *q) { }
block/cfq-iosched.c +5 -32
@@ -1683,30 +1683,6 @@ static void cfq_pd_reset_stats(struct blkg_policy_data *pd)cfqg_stats_reset (&cfqg->dead_stats); } -/* -* Search for the cfq group current task belongs to. request_queue lock must -* be held. -*/ -static struct cfq_group *cfq_lookup_create_cfqg (struct cfq_data *cfqd, -struct blkcg *blkcg) -{ -struct request_queue *q = cfqd->queue; -struct cfq_group *cfqg =NULL ; - -/* avoid lookup for the common case where there's no blkcg */ -if (blkcg == &blkcg_root) { - cfqg = cfqd->root_group; - }else { -struct blkcg_gq *blkg; - - blkg =blkg_lookup_create (blkcg, q); -if (!IS_ERR (blkg)) - cfqg =blkg_to_cfqg (blkg); - } - -return cfqg; -} -static void cfq_link_cfqq_cfqg (struct cfq_queue *cfqq,struct cfq_group *cfqg) { cfqq->cfqg = cfqg;
@@ -2108,12 +2084,6 @@ static struct cftype cfq_blkcg_files[] = { { } /* terminate */ };#else /* GROUP_IOSCHED */ -static struct cfq_group *cfq_lookup_create_cfqg (struct cfq_data *cfqd, -struct blkcg *blkcg) -{ -return cfqd->root_group; -} -static inline void cfq_link_cfqq_cfqg (struct cfq_queue *cfqq,struct cfq_group *cfqg) { cfqq->cfqg = cfqg;
@@ -3711,16 +3681,19 @@ cfq_get_queue(struct cfq_data *cfqd, bool is_sync, struct cfq_io_cq *cic, {int ioprio_class =IOPRIO_PRIO_CLASS (cic->ioprio);int ioprio =IOPRIO_PRIO_DATA (cic->ioprio); +struct blkcg_gq *blkg;struct cfq_queue **async_cfqq =NULL ;struct cfq_queue *cfqq;struct cfq_group *cfqg;rcu_read_lock (); - cfqg =cfq_lookup_create_cfqg (cfqd,bio_blkcg (bio)); -if (!cfqg) { + + blkg =blkg_lookup (bio_blkcg (bio), cfqd->queue); +if (!blkg) { cfqq = &cfqd->oom_cfqq; goto out; } + cfqg =blkg_to_cfqg (blkg);if (!is_sync) {if (!ioprio_valid (cic->ioprio)) {
include/linux/blk-cgroup.h +38 -2
@@ -421,8 +421,8 @@ static inline struct request_list *blk_get_rl(struct request_queue *q,* or if either the blkcg or queue is going away. Fall back to * root_rl in such cases. */ - blkg =blkg_lookup_create (blkcg, q); -if (unlikely (IS_ERR (blkg))) + blkg =blkg_lookup (blkcg, q); +if (unlikely (!blkg)) goto root_rl;blkg_get (blkg);
@@ -636,6 +636,39 @@ static inline void blkg_rwstat_merge(struct blkg_rwstat *to,u64_stats_update_end (&to->syncp); } +#ifdef CONFIG_BLK_DEV_THROTTLING +extern bool blk_throtl_bio (struct request_queue *q,struct blkcg_gq *blkg, +struct bio *bio); +#else +static inline bool blk_throtl_bio (struct request_queue *q,struct blkgc_gq *blkg, +struct bio *bio) {return false; } +#endif + +static inline bool blkcg_bio_issue_check (struct request_queue *q, +struct bio *bio) +{ +struct blkcg *blkcg; +struct blkcg_gq *blkg; +bool throtl = false; + +rcu_read_lock (); + blkcg =bio_blkcg (bio); + + blkg =blkg_lookup (blkcg, q); +if (unlikely (!blkg)) { +spin_lock_irq (q->queue_lock); + blkg =blkg_lookup_create (blkcg, q); +if (IS_ERR (blkg)) + blkg =NULL ; +spin_unlock_irq (q->queue_lock); + } + + throtl =blk_throtl_bio (q, blkg, bio); + +rcu_read_unlock (); +return !throtl; +} +#else /* CONFIG_BLK_CGROUP */ struct blkcg {
@@ -689,6 +722,9 @@ static inline void blk_put_rl(struct request_list *rl) { }static inline void blk_rq_set_rl (struct request *rq,struct request_list *rl) { }static inline struct request_list *blk_rq_rl (struct request *rq) {return &rq->q->root_rl; } +static inline bool blkcg_bio_issue_check (struct request_queue *q, +struct bio *bio) {return true; } +#define blk_queue_for_each_rl (rl, q) \ for ((rl) = &(q)->root_rl; (rl); (rl) = NULL)
Signature · 1 line
2.4.3
Tejun Heo
maintainerPATCH v2 5/10 blkcg: consolidate blkg creation in blkcg_bio_issue_check()
Quoted 1 line
From
d45bbd52ebb22e8a939892630234aec73c8865eaMon Sep 17 00:00:00 2001
From: Tejun Heo <[email protected]>
Date: Wed, 15 Jul 2015 18:34:23 -0400
blkg (blkcg_gq) currently is created by blkcg policies invoking blkg_lookup_create() which ends up repeating about the same code in different policies. Theoretically, this can avoid the overhead of looking and/or creating blkg's if blkcg is enabled but no policy is in use; however, the cost of blkg lookup / creation is very low especially if only the root blkcg is in use which is highly likely if no blkcg policy is in active use - it boils down to a single very predictable conditional and surrounding RCU protection.
This patch consolidates blkg creation to a new function blkcg_bio_issue_check() which is called during bio issue from generic_make_request_checks(). blkcg_bio_issue_check() is now the only function which tries to create missing blkg's. The subsequent policy and request_list operations just perform blkg_lookup() and if missing falls back to the root.
* blk_get_rl() no longer tries to create blkg. It uses blkg_lookup() instead of blkg_lookup_create().
* blk_throtl_bio() is now called from blkcg_bio_issue_check() with rcu read locked and blkg already looked up. Both throtl_lookup_tg() and throtl_lookup_create_tg() are dropped.
* cfq is similarly updated. cfq_lookup_create_cfqg() is replaced with cfq_lookup_cfqg()which uses blkg_lookup().
This consolidates blkg handling and avoids unnecessary blkg creation retries under memory pressure. In addition, this provides a common bio entry point into blkcg where things like common accounting can be performed.
v2: Build fixes for !CONFIG_CFQ_GROUP_IOSCHED and
!CONFIG_BLK_DEV_THROTTLING.
---
Hello,
Build fix. git branch updated accordingly.
Thanks.
block/blk-cgroup.c | 2 +- block/blk-core.c | 4 +-- block/blk-throttle.c | 72 ++++------------------------------------------ block/blk.h | 5 ---- block/cfq-iosched.c | 33 +++++++-------------- include/linux/blk-cgroup.h | 40 ++++++++++++++++++++++++-- 6 files changed, 57 insertions(+), 99 deletions(-)
block/blk-cgroup.c +1 -1
@@ -153,6 +153,7 @@ struct blkcg_gq *blkg_lookup_slowpath(struct blkcg *blkcg,return NULL ; } +EXPORT_SYMBOL_GPL (blkg_lookup_slowpath);/* * If @new_blkg is %NULL, this function tries to allocate a new one as
@@ -295,7 +296,6 @@ struct blkcg_gq *blkg_lookup_create(struct blkcg *blkcg,return blkg; } } -EXPORT_SYMBOL_GPL (blkg_lookup_create);static void blkg_destroy (struct blkcg_gq *blkg) {
block/blk-core.c +2 -2
@@ -1889,8 +1889,8 @@ generic_make_request_checks(struct bio *bio)*/ create_io_context (GFP_ATOMIC , q->node); -if (blk_throtl_bio (q, bio)) -return false;/* throttled, will be resubmitted later */ +if (!blkcg_bio_issue_check (q, bio)) +return false;trace_block_bio_queue (q, bio);return true;
block/blk-throttle.c +6 -66
110 lines not on this page · raw message
block/blk.h +0 -5
@@ -266,15 +266,10 @@ static inline struct io_context *create_io_context(gfp_t gfp_mask, int node)* Internal throttling interface */ #ifdef CONFIG_BLK_DEV_THROTTLING -extern bool blk_throtl_bio (struct request_queue *q,struct bio *bio);extern void blk_throtl_drain (struct request_queue *q);extern int blk_throtl_init (struct request_queue *q);extern void blk_throtl_exit (struct request_queue *q);#else /* CONFIG_BLK_DEV_THROTTLING */ -static inline bool blk_throtl_bio (struct request_queue *q,struct bio *bio) -{ -return false; -}static inline void blk_throtl_drain (struct request_queue *q) { }static inline int blk_throtl_init (struct request_queue *q) {return 0 ; }static inline void blk_throtl_exit (struct request_queue *q) { }
block/cfq-iosched.c +10 -23
@@ -1683,28 +1683,15 @@ static void cfq_pd_reset_stats(struct blkg_policy_data *pd)cfqg_stats_reset (&cfqg->dead_stats); } -/* -* Search for the cfq group current task belongs to. request_queue lock must -* be held. -*/ -static struct cfq_group *cfq_lookup_create_cfqg (struct cfq_data *cfqd, -struct blkcg *blkcg) +static struct cfq_group *cfq_lookup_cfqg (struct cfq_data *cfqd, +struct blkcg *blkcg) { -struct request_queue *q = cfqd->queue; -struct cfq_group *cfqg =NULL ; - -/* avoid lookup for the common case where there's no blkcg */ -if (blkcg == &blkcg_root) { - cfqg = cfqd->root_group; - }else { -struct blkcg_gq *blkg; - - blkg =blkg_lookup_create (blkcg, q); -if (!IS_ERR (blkg)) - cfqg =blkg_to_cfqg (blkg); - } +struct blkcg_gq *blkg; -return cfqg; + blkg =blkg_lookup (blkcg, cfqd->queue); +if (likely (blkg)) +return blkg_to_cfqg (blkg); +return NULL ; }static void cfq_link_cfqq_cfqg (struct cfq_queue *cfqq,struct cfq_group *cfqg)
@@ -2108,8 +2095,8 @@ static struct cftype cfq_blkcg_files[] = { { } /* terminate */ };#else /* GROUP_IOSCHED */ -static struct cfq_group *cfq_lookup_create_cfqg (struct cfq_data *cfqd, -struct blkcg *blkcg) +static struct cfq_group *cfq_lookup_cfqg (struct cfq_data *cfqd, +struct blkcg *blkcg) {return cfqd->root_group; }
@@ -3716,7 +3703,7 @@ cfq_get_queue(struct cfq_data *cfqd, bool is_sync, struct cfq_io_cq *cic,struct cfq_group *cfqg;rcu_read_lock (); - cfqg =cfq_lookup_create_cfqg (cfqd,bio_blkcg (bio)); + cfqg =cfq_lookup_cfqg (cfqd,bio_blkcg (bio));if (!cfqg) { cfqq = &cfqd->oom_cfqq; goto out;
include/linux/blk-cgroup.h +38 -2
@@ -421,8 +421,8 @@ static inline struct request_list *blk_get_rl(struct request_queue *q,* or if either the blkcg or queue is going away. Fall back to * root_rl in such cases. */ - blkg =blkg_lookup_create (blkcg, q); -if (unlikely (IS_ERR (blkg))) + blkg =blkg_lookup (blkcg, q); +if (unlikely (!blkg)) goto root_rl;blkg_get (blkg);
@@ -636,6 +636,39 @@ static inline void blkg_rwstat_merge(struct blkg_rwstat *to,u64_stats_update_end (&to->syncp); } +#ifdef CONFIG_BLK_DEV_THROTTLING +extern bool blk_throtl_bio (struct request_queue *q,struct blkcg_gq *blkg, +struct bio *bio); +#else +static inline bool blk_throtl_bio (struct request_queue *q,struct blkcg_gq *blkg, +struct bio *bio) {return false; } +#endif + +static inline bool blkcg_bio_issue_check (struct request_queue *q, +struct bio *bio) +{ +struct blkcg *blkcg; +struct blkcg_gq *blkg; +bool throtl = false; + +rcu_read_lock (); + blkcg =bio_blkcg (bio); + + blkg =blkg_lookup (blkcg, q); +if (unlikely (!blkg)) { +spin_lock_irq (q->queue_lock); + blkg =blkg_lookup_create (blkcg, q); +if (IS_ERR (blkg)) + blkg =NULL ; +spin_unlock_irq (q->queue_lock); + } + + throtl =blk_throtl_bio (q, blkg, bio); + +rcu_read_unlock (); +return !throtl; +} +#else /* CONFIG_BLK_CGROUP */ struct blkcg {
@@ -689,6 +722,9 @@ static inline void blk_put_rl(struct request_list *rl) { }static inline void blk_rq_set_rl (struct request *rq,struct request_list *rl) { }static inline struct request_list *blk_rq_rl (struct request *rq) {return &rq->q->root_rl; } +static inline bool blkcg_bio_issue_check (struct request_queue *q, +struct bio *bio) {return true; } +#define blk_queue_for_each_rl (rl, q) \ for ((rl) = &(q)->root_rl; (rl); (rl) = NULL)
Signature · 1 line
2.4.3
Tejun Heo
maintainerPATCH 6/10 blkcg: add blkg_[rw]stat->aux_cnt and replace cfq_group->dead_stats with it
In reply to Tejun Heocgroup stats are local to each cgroup and doesn't propagate to ancestors by default. When recursive stats are necessary, the sum is calculated over all the descendants. This initially was for backward compatibility to support both group-local and recursive stats but this mode of operation makes general sense as stat update is much hotter thafn reporting those stats.
This however ends up losing recursive stats when a child is removed. To work around this, cfq-iosched adds its stats to its parent cfq_group->dead_stats which is summed up together when calculating recursive stats.
It's planned that the core stats will be moved to blkcg_gq, so we want to move the mechanism for keeping track of the stats of dead children from cfq to blkcg core. This patch adds blkg_[rw]stat->aux_cnt which are atomic64_t's keeping track of auxiliary counts which are excluded when reading local counts but included for recursive.
blkg_[rw]stat_merge() which were used by cfq to implement dead_stats are replaced by blkg_[rw]stat_add_aux(), and cfq now forwards stats of a dead cgroup to the aux counts of parent->stats instead of separate ->dead_stats.
This will also help making blkg_[rw]stats per-cpu.
--- block/blk-cgroup.c | 10 ++++--- block/cfq-iosched.c | 67 +++++++++++++--------------------------------- include/linux/blk-cgroup.h | 46 ++++++++++++++++++++++--------- 3 files changed, 57 insertions(+), 66 deletions(-)
block/blk-cgroup.c +6 -4
@@ -584,7 +584,7 @@ EXPORT_SYMBOL_GPL(blkg_prfill_rwstat);* @off: offset to the blkg_stat in @pd * * Collect the blkg_stat specified by @off from @pd and all its online -* descendants and return the sum. The caller must be holding the queue +* descendants and their aux counts. The caller must be holding the queue * lock for online tests. */ u64 blkg_stat_recursive_sum (struct blkg_policy_data *pd,int off)
@@ -602,7 +602,8 @@ u64 blkg_stat_recursive_sum(struct blkg_policy_data *pd, int off)struct blkg_stat *stat = (void *)pos_pd + off;if (pos_blkg->online) - sum +=blkg_stat_read (stat); + sum +=blkg_stat_read (stat) + +atomic64_read (&stat->aux_cnt); }rcu_read_unlock ();
@@ -616,7 +617,7 @@ EXPORT_SYMBOL_GPL(blkg_stat_recursive_sum);* @off: offset to the blkg_stat in @pd * * Collect the blkg_rwstat specified by @off from @pd and all its online -* descendants and return the sum. The caller must be holding the queue +* descendants and their aux counts. The caller must be holding the queue * lock for online tests. */ struct blkg_rwstat blkg_rwstat_recursive_sum(struct blkg_policy_data *pd,
@@ -642,7 +643,8 @@ struct blkg_rwstat blkg_rwstat_recursive_sum(struct blkg_policy_data *pd, tmp =blkg_rwstat_read (rwstat);for (i =0 ; i <BLKG_RWSTAT_NR ; i++) - sum.cnt[i] += tmp.cnt[i]; + sum.cnt[i] += tmp.cnt[i] + +atomic64_read (&rwstat->aux_cnt[i]); }rcu_read_unlock ();
block/cfq-iosched.c +18 -49
122 lines not on this page · raw message
include/linux/blk-cgroup.h +33 -13
110 lines not on this page · raw message
Signature · 1 line
2.4.3
Tejun Heo
maintainerPATCH 7/10 blkcg: make blkcg_[rw]stat per-cpu
In reply to Tejun Heoblkcg_[rw]stat are used as stat counters for blkcg policies. It isn't per-cpu by itself and blk-throttle makes it per-cpu by wrapping around it. This patch makes blkcg_[rw]stat per-cpu and drop the ad-hoc per-cpu wrapping in blk-throttle.
* blkg_[rw]stat->cnt is replaced with cpu_cnt which is struct percpu_counter. This makes syncp unnecessary as remote accesses are handled by percpu_counter itself.
* blkg_[rw]stat_init() can now fail due to percpu allocation failure and thus are updated to return int.
* percpu_counters need explicit freeing. blkg_[rw]stat_exit() added.
* As blkg_rwstat->cpu_cnt[] can't be read directly anymore, reading and summing results are stored in ->aux_cnt[] instead.
* Custom per-cpu stat implementation in blk-throttle is removed.
This makes all blkcg stat counters per-cpu without complicating policy implmentations.
--- block/blk-cgroup.c | 10 ++-- block/blk-throttle.c | 89 +++++++++++---------------------- block/cfq-iosched.c | 70 +++++++++++++++++++------- include/linux/blk-cgroup.h | 120 +++++++++++++++++++++++++-------------------- 4 files changed, 153 insertions(+), 136 deletions(-)
block/blk-cgroup.c +6 -4
@@ -539,9 +539,10 @@ u64 __blkg_prfill_rwstat(struct seq_file *sf, struct blkg_policy_data *pd,for (i =0 ; i <BLKG_RWSTAT_NR ; i++)seq_printf (sf,"%s %s %llu\n" , dname, rwstr[i], - (unsigned long long )rwstat->cnt[i]); + (unsigned long long )atomic64_read (&rwstat->aux_cnt[i])); - v = rwstat->cnt[BLKG_RWSTAT_READ ] + rwstat->cnt[BLKG_RWSTAT_WRITE ]; + v =atomic64_read (&rwstat->aux_cnt[BLKG_RWSTAT_READ ]) + +atomic64_read (&rwstat->aux_cnt[BLKG_RWSTAT_WRITE ]);seq_printf (sf,"%s Total %llu\n" , dname, (unsigned long long )v);return v; }
@@ -643,8 +644,9 @@ struct blkg_rwstat blkg_rwstat_recursive_sum(struct blkg_policy_data *pd, tmp =blkg_rwstat_read (rwstat);for (i =0 ; i <BLKG_RWSTAT_NR ; i++) - sum.cnt[i] += tmp.cnt[i] + -atomic64_read (&rwstat->aux_cnt[i]); +atomic64_add (atomic64_read (&tmp.aux_cnt[i]) + +atomic64_read (&rwstat->aux_cnt[i]), + &sum.aux_cnt[i]); }rcu_read_unlock ();
block/blk-throttle.c +28 -61
159 lines not on this page · raw message
block/cfq-iosched.c +52 -18
93 lines not on this page · raw message
include/linux/blk-cgroup.h +67 -53
225 lines not on this page · raw message
Signature · 1 line
2.4.3
Tejun Heo
maintainerPATCH 8/10 blkcg: make blkg_[rw]stat_recursive_sum() to be able to index into blkcg_gq
In reply to Tejun HeoCurrently, blkg_[rw]stat_recursive_sum() assume that the target counter is located in pd (blkg_policy_data); however, some counters are planned to be moved to blkg (blkcg_gq).
This patch updates blkg_[rw]stat_recursive_sum() to take blkg and blkg_policy pointers instead of pd. If policy is NULL, it indexes into blkg. If non-NULL, into the blkg's pd of the policy.
The existing usages are updated to maintain the current behaviors.
--- block/blk-cgroup.c | 69 ++++++++++++++++++++++++++++------------------ block/cfq-iosched.c | 8 +++--- include/linux/blk-cgroup.h | 7 +++-- 3 files changed, 50 insertions(+), 34 deletions(-)
block/blk-cgroup.c +42 -27
@@ -581,30 +581,39 @@ EXPORT_SYMBOL_GPL(blkg_prfill_rwstat);/** * blkg_stat_recursive_sum - collect hierarchical blkg_stat -* @pd: policy private data of interest -* @off: offset to the blkg_stat in @pd +* @blkg: blkg of interest +* @pol: blkcg_policy which contains the blkg_stat +* @off: offset to the blkg_stat in blkg_policy_data or @blkg * -* Collect the blkg_stat specified by @off from @pd and all its online -* descendants and their aux counts. The caller must be holding the queue -* lock for online tests. +* Collect the blkg_stat specified by @blkg, @pol and @off and all its +* online descendants and their aux counts. The caller must be holding the +* queue lock for online tests. +* +* If @pol is NULL, blkg_stat is at @off bytes into @blkg; otherwise, it is +* at @off bytes into @blkg's blkg_policy_data of the policy. */ -u64 blkg_stat_recursive_sum (struct blkg_policy_data *pd,int off) +u64 blkg_stat_recursive_sum (struct blkcg_gq *blkg, +struct blkcg_policy *pol,int off) { -struct blkcg_policy *pol = blkcg_policy[pd->plid];struct blkcg_gq *pos_blkg;struct cgroup_subsys_state *pos_css;u64 sum =0 ; -lockdep_assert_held (pd->blkg->q->queue_lock); +lockdep_assert_held (blkg->q->queue_lock);rcu_read_lock (); -blkg_for_each_descendant_pre (pos_blkg, pos_css,pd_to_blkg (pd)) { -struct blkg_policy_data *pos_pd =blkg_to_pd (pos_blkg, pol); -struct blkg_stat *stat = (void *)pos_pd + off; +blkg_for_each_descendant_pre (pos_blkg, pos_css, blkg) { +struct blkg_stat *stat; + +if (!pos_blkg->online) +continue ; -if (pos_blkg->online) - sum +=blkg_stat_read (stat) + -atomic64_read (&stat->aux_cnt); +if (pol) + stat = (void *)blkg_to_pd (pos_blkg, pol) + off; +else + stat = (void *)blkg + off; + + sum +=blkg_stat_read (stat) +atomic64_read (&stat->aux_cnt); }rcu_read_unlock ();
@@ -614,33 +623,39 @@ EXPORT_SYMBOL_GPL(blkg_stat_recursive_sum);/** * blkg_rwstat_recursive_sum - collect hierarchical blkg_rwstat -* @pd: policy private data of interest -* @off: offset to the blkg_stat in @pd +* @blkg: blkg of interest +* @pol: blkcg_policy which contains the blkg_rwstat +* @off: offset to the blkg_rwstat in blkg_policy_data or @blkg * -* Collect the blkg_rwstat specified by @off from @pd and all its online -* descendants and their aux counts. The caller must be holding the queue -* lock for online tests. +* Collect the blkg_rwstat specified by @blkg, @pol and @off and all its +* online descendants and their aux counts. The caller must be holding the +* queue lock for online tests. +* +* If @pol is NULL, blkg_rwstat is at @off bytes into @blkg; otherwise, it +* is at @off bytes into @blkg's blkg_policy_data of the policy. */ -struct blkg_rwstat blkg_rwstat_recursive_sum (struct blkg_policy_data *pd, -int off) +struct blkg_rwstat blkg_rwstat_recursive_sum (struct blkcg_gq *blkg, +struct blkcg_policy *pol,int off) { -struct blkcg_policy *pol = blkcg_policy[pd->plid];struct blkcg_gq *pos_blkg;struct cgroup_subsys_state *pos_css;struct blkg_rwstat sum = { };int i; -lockdep_assert_held (pd->blkg->q->queue_lock); +lockdep_assert_held (blkg->q->queue_lock);rcu_read_lock (); -blkg_for_each_descendant_pre (pos_blkg, pos_css,pd_to_blkg (pd)) { -struct blkg_policy_data *pos_pd =blkg_to_pd (pos_blkg, pol); -struct blkg_rwstat *rwstat = (void *)pos_pd + off; -struct blkg_rwstat tmp; +blkg_for_each_descendant_pre (pos_blkg, pos_css, blkg) { +struct blkg_rwstat *rwstat, tmp;if (!pos_blkg->online)continue ; +if (pol) + rwstat = (void *)blkg_to_pd (pos_blkg, pol) + off; +else + rwstat = (void *)pos_blkg + off; + tmp =blkg_rwstat_read (rwstat);for (i =0 ; i <BLKG_RWSTAT_NR ; i++)
block/cfq-iosched.c +4 -4
@@ -1875,16 +1875,16 @@ static int cfqg_print_rwstat(struct seq_file *sf, void *v)static u64 cfqg_prfill_stat_recursive (struct seq_file *sf,struct blkg_policy_data *pd,int off) { -u64 sum =blkg_stat_recursive_sum (pd, off); - +u64 sum =blkg_stat_recursive_sum (pd_to_blkg (pd), + &blkcg_policy_cfq, off);return __blkg_prfill_u64 (sf, pd, sum); }static u64 cfqg_prfill_rwstat_recursive (struct seq_file *sf,struct blkg_policy_data *pd,int off) { -struct blkg_rwstat sum =blkg_rwstat_recursive_sum (pd, off); - +struct blkg_rwstat sum =blkg_rwstat_recursive_sum (pd_to_blkg (pd), + &blkcg_policy_cfq, off);return __blkg_prfill_rwstat (sf, pd, &sum); }
include/linux/blk-cgroup.h +4 -3
@@ -191,9 +191,10 @@ u64 blkg_prfill_stat(struct seq_file *sf, struct blkg_policy_data *pd, int off);u64 blkg_prfill_rwstat (struct seq_file *sf,struct blkg_policy_data *pd,int off); -u64 blkg_stat_recursive_sum (struct blkg_policy_data *pd,int off); -struct blkg_rwstat blkg_rwstat_recursive_sum (struct blkg_policy_data *pd, -int off); +u64 blkg_stat_recursive_sum (struct blkcg_gq *blkg, +struct blkcg_policy *pol,int off); +struct blkg_rwstat blkg_rwstat_recursive_sum (struct blkcg_gq *blkg, +struct blkcg_policy *pol,int off);struct blkg_conf_ctx {struct gendisk *disk;
Signature · 1 line
2.4.3
Tejun Heo
maintainerPATCH 9/10 blkcg: move io_service_bytes and io_serviced stats into blkcg_gq
In reply to Tejun HeoCurrently, both cfq-iosched and blk-throttle keep track of io_service_bytes and io_serviced stats. While keeping track of them separately may be useful during development, it doesn't make much sense otherwise. Also, blk-throttle was counting bio's as IOs while cfq-iosched request's, which is more confusing than informative.
This patch adds ->stat_bytes and ->stat_ios to blkg (blkcg_gq), removes the counterparts from cfq-iosched and blk-throttle and let them print from the common blkg counters. The common counters are incremented during bio issue in blkcg_bio_issue_check().
The outputs are still filtered by whether the policy has blkg_policy_data on a given blkg, so cfq's output won't show up if it has never been used for a given blkg. The only times when the outputs would differ significantly are when policies are attached on the fly or elevators are switched back and forth. Those are quite exceptional operations and I don't think they warrant keeping separate counters.
v2: Account IOs during bio issues instead of request completions so
that bio-based drivers can be handled the same way.
--- block/blk-cgroup.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++ block/blk-throttle.c | 73 +++------------------------------- block/cfq-iosched.c | 32 +++++---------- include/linux/blk-cgroup.h | 14 +++++++ 4 files changed, 127 insertions(+), 90 deletions(-)
block/blk-cgroup.c +98 -0
@@ -73,6 +73,9 @@ static void blkg_free(struct blkcg_gq *blkg)if (blkg->blkcg != &blkcg_root)blk_exit_rl (&blkg->rl); + +blkg_rwstat_exit (&blkg->stat_ios); +blkg_rwstat_exit (&blkg->stat_bytes);kfree (blkg); }
@@ -95,6 +98,10 @@ static struct blkcg_gq *blkg_alloc(struct blkcg *blkcg, struct request_queue *q,if (!blkg)return NULL ; +if (blkg_rwstat_init (&blkg->stat_bytes, gfp_mask) || +blkg_rwstat_init (&blkg->stat_ios, gfp_mask)) + goto err_free; + blkg->q = q;INIT_LIST_HEAD (&blkg->q_node); blkg->blkcg = blkcg;
@@ -300,6 +307,7 @@ struct blkcg_gq *blkg_lookup_create(struct blkcg *blkcg,static void blkg_destroy (struct blkcg_gq *blkg) {struct blkcg *blkcg = blkg->blkcg; +struct blkcg_gq *parent = blkg->parent;int i;lockdep_assert_held (blkg->q->queue_lock);
@@ -315,6 +323,12 @@ static void blkg_destroy(struct blkcg_gq *blkg)if (blkg->pd[i] && pol->pd_offline_fn) pol->pd_offline_fn (blkg->pd[i]); } + +if (parent) { +blkg_rwstat_add_aux (&parent->stat_bytes, &blkg->stat_bytes); +blkg_rwstat_add_aux (&parent->stat_ios, &blkg->stat_ios); + } + blkg->online = false;radix_tree_delete (&blkcg->blkg_tree, blkg->q->id);
@@ -431,6 +445,9 @@ static int blkcg_reset_stats(struct cgroup_subsys_state *css,* anyway. If you get hit by a race, retry. */ hlist_for_each_entry (blkg, &blkcg->blkg_list, blkcg_node) { +blkg_rwstat_reset (&blkg->stat_bytes); +blkg_rwstat_reset (&blkg->stat_ios); +for (i =0 ; i <BLKCG_MAX_POLS ; i++) {struct blkcg_policy *pol = blkcg_policy[i];
@@ -579,6 +596,87 @@ u64 blkg_prfill_rwstat(struct seq_file *sf, struct blkg_policy_data *pd, }EXPORT_SYMBOL_GPL (blkg_prfill_rwstat); +static u64 blkg_prfill_rwstat_field (struct seq_file *sf, +struct blkg_policy_data *pd,int off) +{ +struct blkg_rwstat rwstat =blkg_rwstat_read ((void *)pd->blkg + off); + +return __blkg_prfill_rwstat (sf, pd, &rwstat); +} + +/** +* blkg_print_stat_bytes - seq_show callback for blkg->stat_bytes +* @sf: seq_file to print to +* @v: unused +* +* To be used as cftype->seq_show to print blkg->stat_bytes. +* cftype->private must be set to the blkcg_policy. +*/ +int blkg_print_stat_bytes (struct seq_file *sf,void *v) +{ +blkcg_print_blkgs (sf,css_to_blkcg (seq_css (sf)), + blkg_prfill_rwstat_field, (void *)seq_cft (sf)->private, + offsetof(struct blkcg_gq , stat_bytes), true); +return 0 ; +} +EXPORT_SYMBOL_GPL (blkg_print_stat_bytes); + +/** +* blkg_print_stat_bytes - seq_show callback for blkg->stat_ios +* @sf: seq_file to print to +* @v: unused +* +* To be used as cftype->seq_show to print blkg->stat_ios. cftype->private +* must be set to the blkcg_policy. +*/ +int blkg_print_stat_ios (struct seq_file *sf,void *v) +{ +blkcg_print_blkgs (sf,css_to_blkcg (seq_css (sf)), + blkg_prfill_rwstat_field, (void *)seq_cft (sf)->private, + offsetof(struct blkcg_gq , stat_ios), true); +return 0 ; +} +EXPORT_SYMBOL_GPL (blkg_print_stat_ios); + +static u64 blkg_prfill_rwstat_field_recursive (struct seq_file *sf, +struct blkg_policy_data *pd, +int off) +{ +struct blkg_rwstat rwstat =blkg_rwstat_recursive_sum (pd->blkg, +NULL , off); +return __blkg_prfill_rwstat (sf, pd, &rwstat); +} + +/** +* blkg_print_stat_bytes_recursive - recursive version of blkg_print_stat_bytes +* @sf: seq_file to print to +* @v: unused +*/ +int blkg_print_stat_bytes_recursive (struct seq_file *sf,void *v) +{ +blkcg_print_blkgs (sf,css_to_blkcg (seq_css (sf)), + blkg_prfill_rwstat_field_recursive, + (void *)seq_cft (sf)->private, + offsetof(struct blkcg_gq , stat_bytes), true); +return 0 ; +} +EXPORT_SYMBOL_GPL (blkg_print_stat_bytes_recursive); + +/** +* blkg_print_stat_ios_recursive - recursive version of blkg_print_stat_ios +* @sf: seq_file to print to +* @v: unused +*/ +int blkg_print_stat_ios_recursive (struct seq_file *sf,void *v) +{ +blkcg_print_blkgs (sf,css_to_blkcg (seq_css (sf)), + blkg_prfill_rwstat_field_recursive, + (void *)seq_cft (sf)->private, + offsetof(struct blkcg_gq , stat_ios), true); +return 0 ; +} +EXPORT_SYMBOL_GPL (blkg_print_stat_ios_recursive); +/** * blkg_stat_recursive_sum - collect hierarchical blkg_stat * @blkg: blkg of interest
block/blk-throttle.c +6 -67
135 lines not on this page · raw message
block/cfq-iosched.c +9 -23
@@ -177,10 +177,6 @@ enum wl_type_t {struct cfqg_stats {#ifdef CONFIG_CFQ_GROUP_IOSCHED -/* total bytes transferred */ -struct blkg_rwstat service_bytes; -/* total IOs serviced, post merge */ -struct blkg_rwstat serviced;/* number of ios merged */ struct blkg_rwstat merged;/* total time spent on device in ns, may not be accurate w/ queueing */
@@ -696,8 +692,6 @@ static inline void cfqg_stats_update_dispatch(struct cfq_group *cfqg, uint64_t bytes, int rw) {blkg_stat_add (&cfqg->stats.sectors, bytes >>9 ); -blkg_rwstat_add (&cfqg->stats.serviced, rw,1 ); -blkg_rwstat_add (&cfqg->stats.service_bytes, rw, bytes); } static inline void cfqg_stats_update_completion(struct cfq_group *cfqg,
@@ -717,8 +711,6 @@ static inline void cfqg_stats_update_completion(struct cfq_group *cfqg,static void cfqg_stats_reset (struct cfqg_stats *stats) {/* queued stats shouldn't be cleared */ -blkg_rwstat_reset (&stats->service_bytes); -blkg_rwstat_reset (&stats->serviced);blkg_rwstat_reset (&stats->merged);blkg_rwstat_reset (&stats->service_time);blkg_rwstat_reset (&stats->wait_time);
@@ -738,8 +730,6 @@ static void cfqg_stats_reset(struct cfqg_stats *stats)static void cfqg_stats_add_aux (struct cfqg_stats *to,struct cfqg_stats *from) {/* queued stats shouldn't be cleared */ -blkg_rwstat_add_aux (&to->service_bytes, &from->service_bytes); -blkg_rwstat_add_aux (&to->serviced, &from->serviced);blkg_rwstat_add_aux (&to->merged, &from->merged);blkg_rwstat_add_aux (&to->service_time, &from->service_time);blkg_rwstat_add_aux (&to->wait_time, &from->wait_time);
@@ -1544,8 +1534,6 @@ static void cfq_init_cfqg_base(struct cfq_group *cfqg)#ifdef CONFIG_CFQ_GROUP_IOSCHED static void cfqg_stats_exit (struct cfqg_stats *stats) { -blkg_rwstat_exit (&stats->service_bytes); -blkg_rwstat_exit (&stats->serviced);blkg_rwstat_exit (&stats->merged);blkg_rwstat_exit (&stats->service_time);blkg_rwstat_exit (&stats->wait_time);
@@ -1566,9 +1554,7 @@ static void cfqg_stats_exit(struct cfqg_stats *stats)static int cfqg_stats_init (struct cfqg_stats *stats,gfp_t gfp) { - if (blkg_rwstat_init(&stats->service_bytes, gfp) || - blkg_rwstat_init(&stats->serviced, gfp) || - blkg_rwstat_init(&stats->merged, gfp) || + if (blkg_rwstat_init(&stats->merged, gfp) || blkg_rwstat_init(&stats->service_time, gfp) || blkg_rwstat_init(&stats->wait_time, gfp) || blkg_rwstat_init(&stats->queued, gfp) ||
@@ -1983,13 +1969,13 @@ static struct cftype cfq_blkcg_files[] = { }, { .name = "io_service_bytes", - .private = offsetof(struct cfq_group, stats.service_bytes), - .seq_show = cfqg_print_rwstat, + .private = (unsigned long)&blkcg_policy_cfq, + .seq_show = blkg_print_stat_bytes, }, { .name = "io_serviced", - .private = offsetof(struct cfq_group, stats.serviced), - .seq_show = cfqg_print_rwstat, + .private = (unsigned long)&blkcg_policy_cfq, + .seq_show = blkg_print_stat_ios, }, { .name = "io_service_time",
@@ -2025,13 +2011,13 @@ static struct cftype cfq_blkcg_files[] = { }, { .name = "io_service_bytes_recursive", - .private = offsetof(struct cfq_group, stats.service_bytes), - .seq_show = cfqg_print_rwstat_recursive, + .private = (unsigned long)&blkcg_policy_cfq, + .seq_show = blkg_print_stat_bytes_recursive, }, { .name = "io_serviced_recursive", - .private = offsetof(struct cfq_group, stats.serviced), - .seq_show = cfqg_print_rwstat_recursive, + .private = (unsigned long)&blkcg_policy_cfq, + .seq_show = blkg_print_stat_ios_recursive, }, { .name = "io_service_time_recursive",
include/linux/blk-cgroup.h +14 -0
@@ -127,6 +127,9 @@ struct blkcg_gq {/* is this blkg online? protected by both blkcg and q locks */ bool online; +struct blkg_rwstat stat_bytes; +struct blkg_rwstat stat_ios; +struct blkg_policy_data *pd[BLKCG_MAX_POLS ];struct rcu_head rcu_head;
@@ -190,6 +193,10 @@ u64 __blkg_prfill_rwstat(struct seq_file *sf, struct blkg_policy_data *pd,u64 blkg_prfill_stat (struct seq_file *sf,struct blkg_policy_data *pd,int off);u64 blkg_prfill_rwstat (struct seq_file *sf,struct blkg_policy_data *pd,int off); +int blkg_print_stat_bytes (struct seq_file *sf,void *v); +int blkg_print_stat_ios (struct seq_file *sf,void *v); +int blkg_print_stat_bytes_recursive (struct seq_file *sf,void *v); +int blkg_print_stat_ios_recursive (struct seq_file *sf,void *v);u64 blkg_stat_recursive_sum (struct blkcg_gq *blkg,struct blkcg_policy *pol,int off);
@@ -700,6 +707,13 @@ static inline bool blkcg_bio_issue_check(struct request_queue *q, throtl =blk_throtl_bio (q, blkg, bio); +if (!throtl) { + blkg = blkg ?: q->root_blkg; +blkg_rwstat_add (&blkg->stat_bytes, bio->bi_flags, + bio->bi_iter.bi_size); +blkg_rwstat_add (&blkg->stat_ios, bio->bi_flags,1 ); + } +rcu_read_unlock ();return !throtl; }
Signature · 1 line
2.4.3
Re: [PATCH 09/10] blkcg: move io_service_bytes and io_serviced stats into blkcg_gq
Quoted 5 lines · Tejun Heo
Currently, both cfq-iosched and blk-throttle keep track of
io_service_bytesandio_servicedstats. While keeping track of them separately may be useful during development, it doesn't make much sense otherwise. Also, blk-throttle was counting bio's as IOs while cfq-iosched request's, which is more confusing than informative.
Hi Tejun,
So now blkio.io_serviced will switch to accounting number of bios instead of number of requests? I feel given other stats, things are still confusing as other stats will similar name give stats about requests and not bios.
IMHO, for a policy, either all the stats should be in bio or in terms of requests. Having a mix of these is even more confusing.
For example, IIUC, now blkio.io_serviced will keep count in terms of bios while blkio.io_queued will keep count in terms of number of requests.
If we are keeping common stats at block layer (instead of per policy), I am wondering if it will make sense to reflect that in new cgroup files which are common to all policies in that cgroup, instead of being per policy. And deperecate respective per policy stat files over a period of time.
This will have 3 pros.
- We will not have to deal with any user complaints of suddenly switching accounting from request to bio for two cfq knobs.
- It will be less confusion otherwise some CFQ knobs will be bio based while others will be request based.
- It will also get rid of confusion about switching elevators and stat collection etc.
Thanks
Vivek
Tejun Heo
maintainerRe: [PATCH 09/10] blkcg: move io_service_bytes and io_serviced stats into blkcg_gq
Hello, Vivek.
Quoted 7 lines · Vivek Goyal
So now blkio.io_serviced will switch to accounting number of bios instead of number of requests? I feel given other stats, things are still confusing as other stats will similar name give stats about requests and not bios.
IMHO, for a policy, either all the stats should be in bio or in terms of requests. Having a mix of these is even more confusing.
Well, the actual problem is that we have so many stats which are hardly useful except for debugging blkcg itself. Most of these stats aren't meaningful to userland.
Quoted 3 lines
For example, IIUC, now blkio.io_serviced will keep count in terms of bios while blkio.io_queued will keep count in terms of number of requests.
Why does that matter tho? io_queued tracks the number of requests currently queued. It's not an accumulative stat. It isn't possible to meaningfully correlate that stat with anything else there.
Quoted 4 lines
If we are keeping common stats at block layer (instead of per policy), I am wondering if it will make sense to reflect that in new cgroup files which are common to all policies in that cgroup, instead of being per policy. And deperecate respective per policy stat files over a period of time.
So, that's the plan for unified hierarchy and this is the groundwork for that. There's no point in disturbing interface for the traditional hierarchies at this point. We can simply add the new stats and use the new ones only on the unified hierarchy but frankly how many identical stats should we keep? What we're doing is already pretty silly and I don't really want to add more on top.
Thanks.
Signature · 1 line
tejun
Re: [PATCH 09/10] blkcg: move io_service_bytes and io_serviced stats into blkcg_gq
Quoted 28 lines · Tejun Heo
Hello, Vivek.
Quoted 7 lines · Vivek Goyal
So now blkio.io_serviced will switch to accounting number of bios instead of number of requests? I feel given other stats, things are still confusing as other stats will similar name give stats about requests and not bios.
IMHO, for a policy, either all the stats should be in bio or in terms of requests. Having a mix of these is even more confusing.
Well, the actual problem is that we have so many stats which are hardly useful except for debugging blkcg itself. Most of these stats aren't meaningful to userland.
Quoted 3 lines
For example, IIUC, now blkio.io_serviced will keep count in terms of bios while blkio.io_queued will keep count in terms of number of requests.
Why does that matter tho?
io_queuedtracks the number of requests currently queued. It's not an accumulative stat. It isn't possible to meaningfully correlate that stat with anything else there.Quoted 4 lines
If we are keeping common stats at block layer (instead of per policy), I am wondering if it will make sense to reflect that in new cgroup files which are common to all policies in that cgroup, instead of being per policy. And deperecate respective per policy stat files over a period of time.
Quoted 6 lines
So, that's the plan for unified hierarchy and this is the groundwork for that. There's no point in disturbing interface for the traditional hierarchies at this point. We can simply add the new stats and use the new ones only on the unified hierarchy but frankly how many identical stats should we keep? What we're doing is already pretty silly and I don't really want to add more on top.
Hi Tejun,
Ok. I am personally little apprehensive of changing the meaning of current stat, but I can live with it.
Can you please also update the blkio-controller.txt to reflect these changes. I think following sections would require updation.
blkio.throttle.io_serviced
blkio.throttle.io_service_bytes
And we could mention in blkio.io_serviced that accounting is terms of numeber of bios.
Thanks
Vivek
Tejun Heo
maintainerRe: [PATCH 09/10] blkcg: move io_service_bytes and io_serviced stats into blkcg_gq
Hello, Vivek.
Quoted 2 lines · Vivek Goyal
Ok. I am personally little apprehensive of changing the meaning of current stat, but I can live with it.
Sure, if there are use cases which actually get impacted by this, reverting the original stats shouldn't be difficult. I don't think it's likely to matter tho. I mean, we even get sync / async distinction completely wrong in these stats. We're really pumping out garbage.
Quoted 8 lines
Can you please also update the blkio-controller.txt to reflect these changes. I think following sections would require updation.
blkio.throttle.io_serviced
blkio.throttle.io_service_bytesAnd we could mention in blkio.io_serviced that accounting is terms of numeber of bios.
Sure thing.
Thanks.
Signature · 1 line
tejun
Tejun Heo
maintainerPATCH v3 9/10 blkcg: move io_service_bytes and io_serviced stats into blkcg_gq
In reply to Tejun HeoQuoted 1 line
From
4907d0bbf121eb739a38e36878a798a23fc5e418Mon Sep 17 00:00:00 2001
From: Tejun Heo <[email protected]>
Date: Wed, 15 Jul 2015 18:34:24 -0400
Currently, both cfq-iosched and blk-throttle keep track of io_service_bytes and io_serviced stats. While keeping track of them separately may be useful during development, it doesn't make much sense otherwise. Also, blk-throttle was counting bio's as IOs while cfq-iosched request's, which is more confusing than informative.
This patch adds ->stat_bytes and ->stat_ios to blkg (blkcg_gq), removes the counterparts from cfq-iosched and blk-throttle and let them print from the common blkg counters. The common counters are incremented during bio issue in blkcg_bio_issue_check().
The outputs are still filtered by whether the policy has blkg_policy_data on a given blkg, so cfq's output won't show up if it has never been used for a given blkg. The only times when the outputs would differ significantly are when policies are attached on the fly or elevators are switched back and forth. Those are quite exceptional operations and I don't think they warrant keeping separate counters.
v3: Update blkio-controller.txt accordingly.
v2: Account IOs during bio issues instead of request completions so
that bio-based drivers can be handled the same way.
---
Hello,
Documentation updated as suggested by Vivek.
Thanks.
Documentation/cgroups/blkio-controller.txt | 24 ++------ block/blk-cgroup.c | 98 ++++++++++++++++++++++++++++++ block/blk-throttle.c | 73 ++-------------------- block/cfq-iosched.c | 32 +++------- include/linux/blk-cgroup.h | 14 +++++ 5 files changed, 133 insertions(+), 108 deletions(-)
Documentation/cgroups/blkio-controller.txt +6 -18
@@ -201,7 +201,7 @@ Proportional weight policy files specifies the number of bytes. - blkio.io_serviced - - Number of IOs completed to/from the disk by the group. These + - Number of IOs (bio) issued to the disk by the group. These are further divided by the type of operation - read or write, sync or async. First two fields specify the major and minor number of the device, third field specifies the operation type and the fourth field
@@ -327,18 +327,11 @@ Note: If both BW and IOPS rules are specified for a device, then IO is subjected to both the constraints. - blkio.throttle.io_serviced - - Number of IOs (bio) completed to/from the disk by the group (as - seen by throttling policy). These are further divided by the type - of operation - read or write, sync or async. First two fields specify - the major and minor number of the device, third field specifies the - operation type and the fourth field specifies the number of IOs. - - blkio.io_serviced does accounting as seen by CFQ and counts are in - number of requests (struct request). On the other hand, - blkio.throttle.io_serviced counts number of IO in terms of number - of bios as seen by throttling policy. These bios can later be - merged by elevator and total number of requests completed can be - lesser. + - Number of IOs (bio) issued to the disk by the group. These + are further divided by the type of operation - read or write, sync + or async. First two fields specify the major and minor number of the + device, third field specifies the operation type and the fourth field + specifies the number of IOs. - blkio.throttle.io_service_bytes - Number of bytes transferred to/from the disk by the group. These
@@ -347,11 +340,6 @@ Note: If both BW and IOPS rules are specified for a device, then IO is device, third field specifies the operation type and the fourth field specifies the number of bytes. - These numbers should roughly be same as blkio.io_service_bytes as - updated by CFQ. The difference between two is that - blkio.io_service_bytes will not be updated if CFQ is not operating - on request queue. - Common files among various policies ----------------------------------- - blkio.reset_stats
block/blk-cgroup.c +98 -0
134 lines not on this page · raw message
block/blk-throttle.c +6 -67
135 lines not on this page · raw message
block/cfq-iosched.c +9 -23
@@ -177,10 +177,6 @@ enum wl_type_t {struct cfqg_stats {#ifdef CONFIG_CFQ_GROUP_IOSCHED -/* total bytes transferred */ -struct blkg_rwstat service_bytes; -/* total IOs serviced, post merge */ -struct blkg_rwstat serviced;/* number of ios merged */ struct blkg_rwstat merged;/* total time spent on device in ns, may not be accurate w/ queueing */
@@ -696,8 +692,6 @@ static inline void cfqg_stats_update_dispatch(struct cfq_group *cfqg, uint64_t bytes, int rw) {blkg_stat_add (&cfqg->stats.sectors, bytes >>9 ); -blkg_rwstat_add (&cfqg->stats.serviced, rw,1 ); -blkg_rwstat_add (&cfqg->stats.service_bytes, rw, bytes); } static inline void cfqg_stats_update_completion(struct cfq_group *cfqg,
@@ -717,8 +711,6 @@ static inline void cfqg_stats_update_completion(struct cfq_group *cfqg,static void cfqg_stats_reset (struct cfqg_stats *stats) {/* queued stats shouldn't be cleared */ -blkg_rwstat_reset (&stats->service_bytes); -blkg_rwstat_reset (&stats->serviced);blkg_rwstat_reset (&stats->merged);blkg_rwstat_reset (&stats->service_time);blkg_rwstat_reset (&stats->wait_time);
@@ -738,8 +730,6 @@ static void cfqg_stats_reset(struct cfqg_stats *stats)static void cfqg_stats_add_aux (struct cfqg_stats *to,struct cfqg_stats *from) {/* queued stats shouldn't be cleared */ -blkg_rwstat_add_aux (&to->service_bytes, &from->service_bytes); -blkg_rwstat_add_aux (&to->serviced, &from->serviced);blkg_rwstat_add_aux (&to->merged, &from->merged);blkg_rwstat_add_aux (&to->service_time, &from->service_time);blkg_rwstat_add_aux (&to->wait_time, &from->wait_time);
@@ -1544,8 +1534,6 @@ static void cfq_init_cfqg_base(struct cfq_group *cfqg)#ifdef CONFIG_CFQ_GROUP_IOSCHED static void cfqg_stats_exit (struct cfqg_stats *stats) { -blkg_rwstat_exit (&stats->service_bytes); -blkg_rwstat_exit (&stats->serviced);blkg_rwstat_exit (&stats->merged);blkg_rwstat_exit (&stats->service_time);blkg_rwstat_exit (&stats->wait_time);
@@ -1566,9 +1554,7 @@ static void cfqg_stats_exit(struct cfqg_stats *stats)static int cfqg_stats_init (struct cfqg_stats *stats,gfp_t gfp) { - if (blkg_rwstat_init(&stats->service_bytes, gfp) || - blkg_rwstat_init(&stats->serviced, gfp) || - blkg_rwstat_init(&stats->merged, gfp) || + if (blkg_rwstat_init(&stats->merged, gfp) || blkg_rwstat_init(&stats->service_time, gfp) || blkg_rwstat_init(&stats->wait_time, gfp) || blkg_rwstat_init(&stats->queued, gfp) ||
@@ -1994,13 +1980,13 @@ static struct cftype cfq_blkcg_files[] = { }, { .name = "io_service_bytes", - .private = offsetof(struct cfq_group, stats.service_bytes), - .seq_show = cfqg_print_rwstat, + .private = (unsigned long)&blkcg_policy_cfq, + .seq_show = blkg_print_stat_bytes, }, { .name = "io_serviced", - .private = offsetof(struct cfq_group, stats.serviced), - .seq_show = cfqg_print_rwstat, + .private = (unsigned long)&blkcg_policy_cfq, + .seq_show = blkg_print_stat_ios, }, { .name = "io_service_time",
@@ -2036,13 +2022,13 @@ static struct cftype cfq_blkcg_files[] = { }, { .name = "io_service_bytes_recursive", - .private = offsetof(struct cfq_group, stats.service_bytes), - .seq_show = cfqg_print_rwstat_recursive, + .private = (unsigned long)&blkcg_policy_cfq, + .seq_show = blkg_print_stat_bytes_recursive, }, { .name = "io_serviced_recursive", - .private = offsetof(struct cfq_group, stats.serviced), - .seq_show = cfqg_print_rwstat_recursive, + .private = (unsigned long)&blkcg_policy_cfq, + .seq_show = blkg_print_stat_ios_recursive, }, { .name = "io_service_time_recursive",
include/linux/blk-cgroup.h +14 -0
@@ -127,6 +127,9 @@ struct blkcg_gq {/* is this blkg online? protected by both blkcg and q locks */ bool online; +struct blkg_rwstat stat_bytes; +struct blkg_rwstat stat_ios; +struct blkg_policy_data *pd[BLKCG_MAX_POLS ];struct rcu_head rcu_head;
@@ -190,6 +193,10 @@ u64 __blkg_prfill_rwstat(struct seq_file *sf, struct blkg_policy_data *pd,u64 blkg_prfill_stat (struct seq_file *sf,struct blkg_policy_data *pd,int off);u64 blkg_prfill_rwstat (struct seq_file *sf,struct blkg_policy_data *pd,int off); +int blkg_print_stat_bytes (struct seq_file *sf,void *v); +int blkg_print_stat_ios (struct seq_file *sf,void *v); +int blkg_print_stat_bytes_recursive (struct seq_file *sf,void *v); +int blkg_print_stat_ios_recursive (struct seq_file *sf,void *v);u64 blkg_stat_recursive_sum (struct blkcg_gq *blkg,struct blkcg_policy *pol,int off);
@@ -700,6 +707,13 @@ static inline bool blkcg_bio_issue_check(struct request_queue *q, throtl =blk_throtl_bio (q, blkg, bio); +if (!throtl) { + blkg = blkg ?: q->root_blkg; +blkg_rwstat_add (&blkg->stat_bytes, bio->bi_flags, + bio->bi_iter.bi_size); +blkg_rwstat_add (&blkg->stat_ios, bio->bi_flags,1 ); + } +rcu_read_unlock ();return !throtl; }
Signature · 1 line
2.4.3
Tejun Heo
maintainerPATCH 10/10 blkcg: remove cfqg_stats->sectors
In reply to Tejun Heocfq_stats->sectors is a blkg_stat which keeps track of the total number of sectors serviced; however, this can be trivially calculated from blkcg_gq->stat_bytes. The only thing necessary is adding up READs and WRITEs and then dividing by sector size.
Remove cfqg_stats->sectors and make cfq print "sectors" and "sectors_recursive" from stat_bytes.
While this is a bit more code, it removes duplicate stat allocations and updates and ensures that the reported stats stay in tune with each other.
--- block/cfq-iosched.c | 55 +++++++++++++++++++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 19 deletions(-)
block/cfq-iosched.c +36 -19
@@ -185,8 +185,6 @@ struct cfqg_stats {struct blkg_rwstat wait_time;/* number of IOs queued up */ struct blkg_rwstat queued; -/* total sectors transferred */ -struct blkg_stat sectors;/* total disk time and nr sectors dispatched by this group */ struct blkg_stat time;#ifdef CONFIG_DEBUG_BLK_CGROUP
@@ -688,12 +686,6 @@ static inline void cfqg_stats_update_io_merged(struct cfq_group *cfqg, int rw)blkg_rwstat_add (&cfqg->stats.merged, rw,1 ); } -static inline void cfqg_stats_update_dispatch (struct cfq_group *cfqg, -uint64_t bytes,int rw) -{ -blkg_stat_add (&cfqg->stats.sectors, bytes >>9 ); -} -static inline void cfqg_stats_update_completion (struct cfq_group *cfqg,uint64_t start_time,uint64_t io_start_time,int rw) {
@@ -782,8 +774,6 @@ static inline void cfqg_stats_update_timeslice_used(struct cfq_group *cfqg, unsigned long time, unsigned long unaccounted_time) { }static inline void cfqg_stats_update_io_remove (struct cfq_group *cfqg,int rw) { }static inline void cfqg_stats_update_io_merged (struct cfq_group *cfqg,int rw) { } -static inline void cfqg_stats_update_dispatch (struct cfq_group *cfqg, -uint64_t bytes,int rw) { }static inline void cfqg_stats_update_completion (struct cfq_group *cfqg,uint64_t start_time,uint64_t io_start_time,int rw) { }
@@ -1538,8 +1528,6 @@ static void cfqg_stats_exit(struct cfqg_stats *stats)blkg_rwstat_exit (&stats->service_time);blkg_rwstat_exit (&stats->wait_time);blkg_rwstat_exit (&stats->queued); - -blkg_stat_exit (&stats->sectors);blkg_stat_exit (&stats->time);#ifdef CONFIG_DEBUG_BLK_CGROUP blkg_stat_exit (&stats->unaccounted_time);
@@ -1558,8 +1546,6 @@ static int cfqg_stats_init(struct cfqg_stats *stats, gfp_t gfp)blkg_rwstat_init (&stats->service_time, gfp) ||blkg_rwstat_init (&stats->wait_time, gfp) ||blkg_rwstat_init (&stats->queued, gfp) || - -blkg_stat_init (&stats->sectors, gfp) || blkg_stat_init(&stats->time, gfp)) goto err;
@@ -1890,6 +1876,40 @@ static int cfqg_print_rwstat_recursive(struct seq_file *sf, void *v)return 0 ; } +static u64 cfqg_prfill_sectors (struct seq_file *sf,struct blkg_policy_data *pd, +int off) +{ +u64 sum =blkg_rwstat_total (&pd->blkg->stat_bytes); + +return __blkg_prfill_u64 (sf, pd, sum >>9 ); +} + +static int cfqg_print_stat_sectors (struct seq_file *sf,void *v) +{ +blkcg_print_blkgs (sf,css_to_blkcg (seq_css (sf)), + cfqg_prfill_sectors, &blkcg_policy_cfq,0 , false); +return 0 ; +} + +static u64 cfqg_prfill_sectors_recursive (struct seq_file *sf, +struct blkg_policy_data *pd,int off) +{ +struct blkg_rwstat tmp =blkg_rwstat_recursive_sum (pd->blkg,NULL , + offsetof(struct blkcg_gq , stat_bytes)); +u64 sum =atomic64_read (&tmp.aux_cnt[BLKG_RWSTAT_READ ]) + +atomic64_read (&tmp.aux_cnt[BLKG_RWSTAT_WRITE ]); + +return __blkg_prfill_u64 (sf, pd, sum >>9 ); +} + +static int cfqg_print_stat_sectors_recursive (struct seq_file *sf,void *v) +{ +blkcg_print_blkgs (sf,css_to_blkcg (seq_css (sf)), + cfqg_prfill_sectors_recursive, &blkcg_policy_cfq,0 , + false); +return 0 ; +} +#ifdef CONFIG_DEBUG_BLK_CGROUP static u64 cfqg_prfill_avg_queue_size (struct seq_file *sf,struct blkg_policy_data *pd,int off)
@@ -1964,8 +1984,7 @@ static struct cftype cfq_blkcg_files[] = { }, { .name = "sectors", - .private = offsetof(struct cfq_group, stats.sectors), - .seq_show = cfqg_print_stat, + .seq_show = cfqg_print_stat_sectors, }, { .name = "io_service_bytes",
@@ -2006,8 +2025,7 @@ static struct cftype cfq_blkcg_files[] = { }, { .name = "sectors_recursive", - .private = offsetof(struct cfq_group, stats.sectors), - .seq_show = cfqg_print_stat_recursive, + .seq_show = cfqg_print_stat_sectors_recursive, }, { .name = "io_service_bytes_recursive",
@@ -2871,7 +2889,6 @@ static void cfq_dispatch_insert(struct request_queue *q, struct request *rq) cfqd->rq_in_flight[cfq_cfqq_sync (cfqq)]++; cfqq->nr_sectors +=blk_rq_sectors (rq); -cfqg_stats_update_dispatch (cfqq->cfqg,blk_rq_bytes (rq), rq->cmd_flags); }/*
Signature · 1 line
2.4.3
Tejun Heo
maintainer[PATCH 11/10] blkcg: reduce stack usage of blkg_rwstat_recursive_sum()
In reply to Tejun HeoQuoted 1 line
From
8c6417cb56c71efd47d28d15bc117567f3171c93Mon Sep 17 00:00:00 2001
From: Tejun Heo <[email protected]>
Date: Thu, 16 Jul 2015 11:50:49 -0400
The recent percpu conversion of blkg_rwstat triggered the following warning in certain configurations.
block/blk-cgroup.c:654:1: warning: the frame size of 1360 bytes is larger than 1024 bytes
This is because blkg_rwstat now contains four percpu_counter which can be pretty big depending on debug options although it shouldn't be a problem in production configs. This patch removes one of the two local blkg_rwstat variables used by blkg_rwstat_recursive_sum() to reduce stack usage.
---
Hello,
One extra patch to deal with stack usage bloat under debug configs which came with percpu_counter conversion. git branch updated accordingly.
Thanks.
block/blk-cgroup.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-)
block/blk-cgroup.c +4 -6
@@ -744,7 +744,7 @@ struct blkg_rwstat blkg_rwstat_recursive_sum(struct blkcg_gq *blkg,rcu_read_lock ();blkg_for_each_descendant_pre (pos_blkg, pos_css, blkg) { -struct blkg_rwstat *rwstat, tmp; +struct blkg_rwstat *rwstat;if (!pos_blkg->online)continue ;
@@ -754,12 +754,10 @@ struct blkg_rwstat blkg_rwstat_recursive_sum(struct blkcg_gq *blkg,else rwstat = (void *)pos_blkg + off; - tmp =blkg_rwstat_read (rwstat); -for (i =0 ; i <BLKG_RWSTAT_NR ; i++) -atomic64_add (atomic64_read (&tmp.aux_cnt[i]) + -atomic64_read (&rwstat->aux_cnt[i]), - &sum.aux_cnt[i]); +atomic64_add (atomic64_read (&rwstat->aux_cnt[i]) + +percpu_counter_sum_positive (&rwstat->cpu_cnt[i]), + &sum.aux_cnt[i]); }rcu_read_unlock ();
Signature · 1 line
2.4.3