* [PATCH] Pass the task_struct explicitly to delayacct_blkio_end
@ 2017-12-15 18:11 Josh Snyder
2017-12-18 11:34 ` Peter Zijlstra
0 siblings, 1 reply; 5+ messages in thread
From: Josh Snyder @ 2017-12-15 18:11 UTC (permalink / raw)
To: linux-kernel
Cc: Jens Axboe, Brendan Gregg, linux-block, Tejun Heo, Josh Snyder,
Balbir Singh, Ingo Molnar, Peter Zijlstra
Before e33a9bba85a8, delayacct_blkio_end was called after
context-switching into the task which completed I/O. This resulted in
double counting: the task would account a delay both waiting for I/O and
for time spent in the runqueue.
With e33a9bba85a8, delayacct_blkio_end is called by try_to_wake_up. In
ttwu, we have not yet context-switched. This is more correct, in that the
delay accounting ends when the I/O is complete. But delayacct_blkio_end
relies upon `get_current()`, and we have not yet context-switched into the
task whose I/O completed. This results in the wrong task having its delay
accounting statistics updated.
Instead of doing that, pass the task_struct being woken to
delayacct_blkio_end, so that it can update the statistics of the correct
task_struct.
---
include/linux/delayacct.h | 8 ++++----
kernel/delayacct.c | 42 ++++++++++++++++++++++++++----------------
kernel/sched/core.c | 6 +++---
3 files changed, 33 insertions(+), 23 deletions(-)
diff --git a/include/linux/delayacct.h b/include/linux/delayacct.h
index 4178d24..f2ad868 100644
--- a/include/linux/delayacct.h
+++ b/include/linux/delayacct.h
@@ -71,7 +71,7 @@ extern void delayacct_init(void);
extern void __delayacct_tsk_init(struct task_struct *);
extern void __delayacct_tsk_exit(struct task_struct *);
extern void __delayacct_blkio_start(void);
-extern void __delayacct_blkio_end(void);
+extern void __delayacct_blkio_end(struct task_struct *);
extern int __delayacct_add_tsk(struct taskstats *, struct task_struct *);
extern __u64 __delayacct_blkio_ticks(struct task_struct *);
extern void __delayacct_freepages_start(void);
@@ -122,10 +122,10 @@ static inline void delayacct_blkio_start(void)
__delayacct_blkio_start();
}
-static inline void delayacct_blkio_end(void)
+static inline void delayacct_blkio_end(struct task_struct *p)
{
if (current->delays)
- __delayacct_blkio_end();
+ __delayacct_blkio_end(p);
delayacct_clear_flag(DELAYACCT_PF_BLKIO);
}
@@ -169,7 +169,7 @@ static inline void delayacct_tsk_free(struct task_struct *tsk)
{}
static inline void delayacct_blkio_start(void)
{}
-static inline void delayacct_blkio_end(void)
+static inline void delayacct_blkio_end(struct task_struct *p)
{}
static inline int delayacct_add_tsk(struct taskstats *d,
struct task_struct *tsk)
diff --git a/kernel/delayacct.c b/kernel/delayacct.c
index 4a1c334..e2ec808 100644
--- a/kernel/delayacct.c
+++ b/kernel/delayacct.c
@@ -51,16 +51,16 @@ void __delayacct_tsk_init(struct task_struct *tsk)
* Finish delay accounting for a statistic using its timestamps (@start),
* accumalator (@total) and @count
*/
-static void delayacct_end(u64 *start, u64 *total, u32 *count)
+static void delayacct_end(spinlock_t *lock, u64 *start, u64 *total, u32 *count)
{
s64 ns = ktime_get_ns() - *start;
unsigned long flags;
if (ns > 0) {
- spin_lock_irqsave(¤t->delays->lock, flags);
+ spin_lock_irqsave(lock, flags);
*total += ns;
(*count)++;
- spin_unlock_irqrestore(¤t->delays->lock, flags);
+ spin_unlock_irqrestore(lock, flags);
}
}
@@ -69,17 +69,25 @@ void __delayacct_blkio_start(void)
current->delays->blkio_start = ktime_get_ns();
}
-void __delayacct_blkio_end(void)
+/*
+ * We cannot rely on the `current` macro, as we haven't yet switched back to
+ * the process being woken.
+ */
+void __delayacct_blkio_end(struct task_struct *p)
{
- if (current->delays->flags & DELAYACCT_PF_SWAPIN)
- /* Swapin block I/O */
- delayacct_end(¤t->delays->blkio_start,
- ¤t->delays->swapin_delay,
- ¤t->delays->swapin_count);
- else /* Other block I/O */
- delayacct_end(¤t->delays->blkio_start,
- ¤t->delays->blkio_delay,
- ¤t->delays->blkio_count);
+ struct task_delay_info * delays = p->delays;
+ u64 *total;
+ u32 *count;
+
+ if (p->delays->flags & DELAYACCT_PF_SWAPIN) {
+ total = &delays->swapin_delay;
+ count = &delays->swapin_count;
+ } else {
+ total = &delays->blkio_delay;
+ count = &delays->blkio_count;
+ }
+
+ delayacct_end(&delays->lock, &delays->blkio_start, total, count);
}
int __delayacct_add_tsk(struct taskstats *d, struct task_struct *tsk)
@@ -153,8 +161,10 @@ void __delayacct_freepages_start(void)
void __delayacct_freepages_end(void)
{
- delayacct_end(¤t->delays->freepages_start,
- ¤t->delays->freepages_delay,
- ¤t->delays->freepages_count);
+ delayacct_end(
+ ¤t->delays->lock,
+ ¤t->delays->freepages_start,
+ ¤t->delays->freepages_delay,
+ ¤t->delays->freepages_count);
}
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 75554f3..deda018 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -2056,7 +2056,7 @@ try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags)
p->state = TASK_WAKING;
if (p->in_iowait) {
- delayacct_blkio_end();
+ delayacct_blkio_end(p);
atomic_dec(&task_rq(p)->nr_iowait);
}
@@ -2069,7 +2069,7 @@ try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags)
#else /* CONFIG_SMP */
if (p->in_iowait) {
- delayacct_blkio_end();
+ delayacct_blkio_end(p);
atomic_dec(&task_rq(p)->nr_iowait);
}
@@ -2122,7 +2122,7 @@ static void try_to_wake_up_local(struct task_struct *p, struct rq_flags *rf)
if (!task_on_rq_queued(p)) {
if (p->in_iowait) {
- delayacct_blkio_end();
+ delayacct_blkio_end(p);
atomic_dec(&rq->nr_iowait);
}
ttwu_activate(rq, p, ENQUEUE_WAKEUP | ENQUEUE_NOCLOCK);
--
2.7.4
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH] Pass the task_struct explicitly to delayacct_blkio_end
2017-12-15 18:11 [PATCH] Pass the task_struct explicitly to delayacct_blkio_end Josh Snyder
@ 2017-12-18 11:34 ` Peter Zijlstra
2017-12-18 16:15 ` [PATCH v2] delayacct: Account blkio completion on the correct task Josh Snyder
0 siblings, 1 reply; 5+ messages in thread
From: Peter Zijlstra @ 2017-12-18 11:34 UTC (permalink / raw)
To: Josh Snyder
Cc: linux-kernel, Jens Axboe, Brendan Gregg, linux-block, Tejun Heo,
Balbir Singh, Ingo Molnar
On Fri, Dec 15, 2017 at 06:11:43PM +0000, Josh Snyder wrote:
> Subject: [PATCH] Pass the task_struct explicitly to delayacct_blkio_end
That subject is crap; it needs a subsystem prefix and it needs to
describe what is done, not how its done.
Something like:
delayacct: Fix double accounting for blk-io
> Before e33a9bba85a8, delayacct_blkio_end was called after
> context-switching into the task which completed I/O. This resulted in
> double counting: the task would account a delay both waiting for I/O and
> for time spent in the runqueue.
>
> With e33a9bba85a8, delayacct_blkio_end is called by try_to_wake_up. In
> ttwu, we have not yet context-switched. This is more correct, in that the
> delay accounting ends when the I/O is complete. But delayacct_blkio_end
> relies upon `get_current()`, and we have not yet context-switched into the
> task whose I/O completed. This results in the wrong task having its delay
> accounting statistics updated.
The correct way to quote a commit is like:
e33a9bba85a8 ("sched/core: move IO scheduling accounting from io_schedule_timeout() into scheduler")
> Instead of doing that, pass the task_struct being woken to
> delayacct_blkio_end, so that it can update the statistics of the correct
> task_struct.
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v2] delayacct: Account blkio completion on the correct task
2017-12-18 11:34 ` Peter Zijlstra
@ 2017-12-18 16:15 ` Josh Snyder
2018-01-11 18:04 ` Tejun Heo
2018-01-13 8:26 ` Balbir Singh
0 siblings, 2 replies; 5+ messages in thread
From: Josh Snyder @ 2017-12-18 16:15 UTC (permalink / raw)
To: Peter Zijlstra
Cc: Brendan Gregg, Tejun Heo, linux-block, Jens Axboe, Josh Snyder,
Balbir Singh, Ingo Molnar, open list
Before commit e33a9bba85a8 ("sched/core: move IO scheduling accounting from
io_schedule_timeout() into scheduler"), delayacct_blkio_end was called after
context-switching into the task which completed I/O. This resulted in double
counting: the task would account a delay both waiting for I/O and for time
spent in the runqueue.
With e33a9bba85a8, delayacct_blkio_end is called by try_to_wake_up. In
ttwu, we have not yet context-switched. This is more correct, in that the
delay accounting ends when the I/O is complete. But delayacct_blkio_end
relies upon `get_current()`, and we have not yet context-switched into the
task whose I/O completed. This results in the wrong task having its delay
accounting statistics updated.
Instead of doing that, pass the task_struct being woken to
delayacct_blkio_end, so that it can update the statistics of the correct
task.
Fixes: e33a9bba85a8 ("sched/core: move IO scheduling accounting from io_schedule_timeout() into scheduler")
Signed-off-by: Josh Snyder <joshs@netflix.com>
---
include/linux/delayacct.h | 8 ++++----
kernel/delayacct.c | 42 ++++++++++++++++++++++++++----------------
kernel/sched/core.c | 6 +++---
3 files changed, 33 insertions(+), 23 deletions(-)
diff --git a/include/linux/delayacct.h b/include/linux/delayacct.h
index 4178d24..f2ad868 100644
--- a/include/linux/delayacct.h
+++ b/include/linux/delayacct.h
@@ -71,7 +71,7 @@ extern void delayacct_init(void);
extern void __delayacct_tsk_init(struct task_struct *);
extern void __delayacct_tsk_exit(struct task_struct *);
extern void __delayacct_blkio_start(void);
-extern void __delayacct_blkio_end(void);
+extern void __delayacct_blkio_end(struct task_struct *);
extern int __delayacct_add_tsk(struct taskstats *, struct task_struct *);
extern __u64 __delayacct_blkio_ticks(struct task_struct *);
extern void __delayacct_freepages_start(void);
@@ -122,10 +122,10 @@ static inline void delayacct_blkio_start(void)
__delayacct_blkio_start();
}
-static inline void delayacct_blkio_end(void)
+static inline void delayacct_blkio_end(struct task_struct *p)
{
if (current->delays)
- __delayacct_blkio_end();
+ __delayacct_blkio_end(p);
delayacct_clear_flag(DELAYACCT_PF_BLKIO);
}
@@ -169,7 +169,7 @@ static inline void delayacct_tsk_free(struct task_struct *tsk)
{}
static inline void delayacct_blkio_start(void)
{}
-static inline void delayacct_blkio_end(void)
+static inline void delayacct_blkio_end(struct task_struct *p)
{}
static inline int delayacct_add_tsk(struct taskstats *d,
struct task_struct *tsk)
diff --git a/kernel/delayacct.c b/kernel/delayacct.c
index 4a1c334..e2ec808 100644
--- a/kernel/delayacct.c
+++ b/kernel/delayacct.c
@@ -51,16 +51,16 @@ void __delayacct_tsk_init(struct task_struct *tsk)
* Finish delay accounting for a statistic using its timestamps (@start),
* accumalator (@total) and @count
*/
-static void delayacct_end(u64 *start, u64 *total, u32 *count)
+static void delayacct_end(spinlock_t *lock, u64 *start, u64 *total, u32 *count)
{
s64 ns = ktime_get_ns() - *start;
unsigned long flags;
if (ns > 0) {
- spin_lock_irqsave(¤t->delays->lock, flags);
+ spin_lock_irqsave(lock, flags);
*total += ns;
(*count)++;
- spin_unlock_irqrestore(¤t->delays->lock, flags);
+ spin_unlock_irqrestore(lock, flags);
}
}
@@ -69,17 +69,25 @@ void __delayacct_blkio_start(void)
current->delays->blkio_start = ktime_get_ns();
}
-void __delayacct_blkio_end(void)
+/*
+ * We cannot rely on the `current` macro, as we haven't yet switched back to
+ * the process being woken.
+ */
+void __delayacct_blkio_end(struct task_struct *p)
{
- if (current->delays->flags & DELAYACCT_PF_SWAPIN)
- /* Swapin block I/O */
- delayacct_end(¤t->delays->blkio_start,
- ¤t->delays->swapin_delay,
- ¤t->delays->swapin_count);
- else /* Other block I/O */
- delayacct_end(¤t->delays->blkio_start,
- ¤t->delays->blkio_delay,
- ¤t->delays->blkio_count);
+ struct task_delay_info *delays = p->delays;
+ u64 *total;
+ u32 *count;
+
+ if (p->delays->flags & DELAYACCT_PF_SWAPIN) {
+ total = &delays->swapin_delay;
+ count = &delays->swapin_count;
+ } else {
+ total = &delays->blkio_delay;
+ count = &delays->blkio_count;
+ }
+
+ delayacct_end(&delays->lock, &delays->blkio_start, total, count);
}
int __delayacct_add_tsk(struct taskstats *d, struct task_struct *tsk)
@@ -153,8 +161,10 @@ void __delayacct_freepages_start(void)
void __delayacct_freepages_end(void)
{
- delayacct_end(¤t->delays->freepages_start,
- ¤t->delays->freepages_delay,
- ¤t->delays->freepages_count);
+ delayacct_end(
+ ¤t->delays->lock,
+ ¤t->delays->freepages_start,
+ ¤t->delays->freepages_delay,
+ ¤t->delays->freepages_count);
}
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 75554f3..deda018 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -2056,7 +2056,7 @@ try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags)
p->state = TASK_WAKING;
if (p->in_iowait) {
- delayacct_blkio_end();
+ delayacct_blkio_end(p);
atomic_dec(&task_rq(p)->nr_iowait);
}
@@ -2069,7 +2069,7 @@ try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags)
#else /* CONFIG_SMP */
if (p->in_iowait) {
- delayacct_blkio_end();
+ delayacct_blkio_end(p);
atomic_dec(&task_rq(p)->nr_iowait);
}
@@ -2122,7 +2122,7 @@ static void try_to_wake_up_local(struct task_struct *p, struct rq_flags *rf)
if (!task_on_rq_queued(p)) {
if (p->in_iowait) {
- delayacct_blkio_end();
+ delayacct_blkio_end(p);
atomic_dec(&rq->nr_iowait);
}
ttwu_activate(rq, p, ENQUEUE_WAKEUP | ENQUEUE_NOCLOCK);
--
2.7.4
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH v2] delayacct: Account blkio completion on the correct task
2017-12-18 16:15 ` [PATCH v2] delayacct: Account blkio completion on the correct task Josh Snyder
@ 2018-01-11 18:04 ` Tejun Heo
2018-01-13 8:26 ` Balbir Singh
1 sibling, 0 replies; 5+ messages in thread
From: Tejun Heo @ 2018-01-11 18:04 UTC (permalink / raw)
To: Josh Snyder
Cc: Peter Zijlstra, Brendan Gregg, linux-block, Jens Axboe,
Balbir Singh, Ingo Molnar, open list
Hello,
On Mon, Dec 18, 2017 at 04:15:10PM +0000, Josh Snyder wrote:
> Before commit e33a9bba85a8 ("sched/core: move IO scheduling accounting from
> io_schedule_timeout() into scheduler"), delayacct_blkio_end was called after
> context-switching into the task which completed I/O. This resulted in double
> counting: the task would account a delay both waiting for I/O and for time
> spent in the runqueue.
>
> With e33a9bba85a8, delayacct_blkio_end is called by try_to_wake_up. In
> ttwu, we have not yet context-switched. This is more correct, in that the
> delay accounting ends when the I/O is complete. But delayacct_blkio_end
> relies upon `get_current()`, and we have not yet context-switched into the
> task whose I/O completed. This results in the wrong task having its delay
> accounting statistics updated.
>
> Instead of doing that, pass the task_struct being woken to
> delayacct_blkio_end, so that it can update the statistics of the correct
> task.
>
> Fixes: e33a9bba85a8 ("sched/core: move IO scheduling accounting from io_schedule_timeout() into scheduler")
> Signed-off-by: Josh Snyder <joshs@netflix.com>
Acked-by: Tejun Heo <tj@kernel.org>
Thanks.
--
tejun
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v2] delayacct: Account blkio completion on the correct task
2017-12-18 16:15 ` [PATCH v2] delayacct: Account blkio completion on the correct task Josh Snyder
2018-01-11 18:04 ` Tejun Heo
@ 2018-01-13 8:26 ` Balbir Singh
1 sibling, 0 replies; 5+ messages in thread
From: Balbir Singh @ 2018-01-13 8:26 UTC (permalink / raw)
To: Josh Snyder
Cc: Peter Zijlstra, Brendan Gregg, Tejun Heo, linux-block, Jens Axboe,
Ingo Molnar, open list
On Mon, Dec 18, 2017 at 9:45 PM, Josh Snyder <joshs@netflix.com> wrote:
> Before commit e33a9bba85a8 ("sched/core: move IO scheduling accounting from
> io_schedule_timeout() into scheduler"), delayacct_blkio_end was called after
> context-switching into the task which completed I/O. This resulted in double
> counting: the task would account a delay both waiting for I/O and for time
> spent in the runqueue.
>
Yes, we included the time spent in the runqueue to delays on account of I/O.
> With e33a9bba85a8, delayacct_blkio_end is called by try_to_wake_up. In
> ttwu, we have not yet context-switched. This is more correct, in that the
> delay accounting ends when the I/O is complete. But delayacct_blkio_end
> relies upon `get_current()`, and we have not yet context-switched into the
> task whose I/O completed. This results in the wrong task having its delay
> accounting statistics updated.
>
> Instead of doing that, pass the task_struct being woken to
> delayacct_blkio_end, so that it can update the statistics of the correct
> task.
>
> Fixes: e33a9bba85a8 ("sched/core: move IO scheduling accounting from io_schedule_timeout() into scheduler")
> Signed-off-by: Josh Snyder <joshs@netflix.com>
> ---
Acked-by: Balbir Singh <bsingharora@gmail.com>
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2018-01-13 8:26 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-12-15 18:11 [PATCH] Pass the task_struct explicitly to delayacct_blkio_end Josh Snyder
2017-12-18 11:34 ` Peter Zijlstra
2017-12-18 16:15 ` [PATCH v2] delayacct: Account blkio completion on the correct task Josh Snyder
2018-01-11 18:04 ` Tejun Heo
2018-01-13 8:26 ` Balbir Singh
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).