From: Peter Zijlstra <a.p.zijlstra@chello.nl>
To: Miklos Szeredi <miklos@szeredi.hu>
Cc: linux-mm@kvack.org, linux-kernel@vger.kernel.org,
akpm@linux-foundation.org, neilb@suse.de, dgc@sgi.com,
tomoki.sekiyama.qu@hitachi.com
Subject: Re: [PATCH 6/6] mm: per device dirty threshold
Date: Wed, 04 Apr 2007 12:16:34 +0200 [thread overview]
Message-ID: <1175681794.6483.43.camel@twins> (raw)
In-Reply-To: <E1HZ1so-0005q8-00@dorka.pomaz.szeredi.hu>
On Wed, 2007-04-04 at 11:34 +0200, Miklos Szeredi wrote:
> > Scale writeback cache per backing device, proportional to its writeout speed.
> >
> > akpm sayeth:
> > > Which problem are we trying to solve here? afaik our two uppermost
> > > problems are:
> > >
> > > a) Heavy write to queue A causes light writer to queue B to blok for a long
> > > time in balance_dirty_pages(). Even if the devices have the same speed.
> >
> > This one; esp when not the same speed. The - my usb stick makes my
> > computer suck - problem. But even on similar speed, the separation of
> > device should avoid blocking dev B when dev A is being throttled.
> >
> > The writeout speed is measure dynamically, so when it doesn't have
> > anything to write out for a while its writeback cache size goes to 0.
> >
> > Conversely, when starting up it will in the beginning act almost
> > synchronous but will quickly build up a 'fair' share of the writeback
> > cache.
>
> I'm worried about two things:
>
> 1) If the per-bdi threshold becomes smaller than the granularity of
> the per-bdi stat (due to the per-CPU counters), then things will
> break. Shouldn't there be some sanity checking for the calculated
> threshold?
I'm not sure what you're referring to.
void get_writeout_scale(struct backing_dev_info *bdi, int *scale, int *div)
{
int bits = vm_cycle_shift - 1;
unsigned long total = __global_bdi_stat(BDI_WRITEOUT_TOTAL);
unsigned long cycle = 1UL << bits;
unsigned long mask = cycle - 1;
if (bdi_cap_writeback_dirty(bdi)) {
bdi_writeout_norm(bdi);
*scale = __bdi_stat(bdi, BDI_WRITEOUT);
} else
*scale = 0;
*div = cycle + (total & mask);
}
where cycle ~ vm_total_pages
scale can be a tad off due to overstep here:
void __inc_bdi_stat(struct backing_dev_info *bdi, enum bdi_stat_item item)
{
struct bdi_per_cpu_data *pcd = &bdi->pcd[smp_processor_id()];
s8 *p = pcd->bdi_stat_diff + item;
(*p)++;
if (unlikely(*p > pcd->stat_threshold)) {
int overstep = pcd->stat_threshold / 2;
bdi_stat_add(*p + overstep, bdi, item);
*p = -overstep;
}
}
so it could be that: scale / cycle > 1
by a very small amount; however:
if (bdi) {
long long tmp = dirty;
long reserve;
int scale, div;
get_writeout_scale(bdi, &scale, &div);
tmp *= scale;
do_div(tmp, div);
reserve = dirty -
(global_bdi_stat(BDI_DIRTY) +
global_bdi_stat(BDI_WRITEBACK) +
global_bdi_stat(BDI_UNSTABLE));
if (reserve < 0)
reserve = 0;
reserve += bdi_stat(bdi, BDI_DIRTY) +
bdi_stat(bdi, BDI_WRITEBACK) +
bdi_stat(bdi, BDI_UNSTABLE);
*pbdi_dirty = min((long)tmp, reserve);
}
here we clip to 'reserve' which is the total amount of dirty threshold
not dirty by others.
> 2) The loop is sleeping in congestion_wait(WRITE), which seems wrong.
> It may well be possible that none of the queues are congested, so
> it will sleep the full .1 second. But by that time the queue may
> have become idle and is just sitting there doing nothing. Maybe
> there should be a per-bdi waitq, that is woken up, when the per-bdi
> stats are updated.
Good point, .1 seconds is a lot of time.
I'll cook up something like that if nobody beats me to it :-)
WARNING: multiple messages have this Message-ID (diff)
From: Peter Zijlstra <a.p.zijlstra@chello.nl>
To: Miklos Szeredi <miklos@szeredi.hu>
Cc: linux-mm@kvack.org, linux-kernel@vger.kernel.org,
akpm@linux-foundation.org, neilb@suse.de, dgc@sgi.com,
tomoki.sekiyama.qu@hitachi.com
Subject: Re: [PATCH 6/6] mm: per device dirty threshold
Date: Wed, 04 Apr 2007 12:16:34 +0200 [thread overview]
Message-ID: <1175681794.6483.43.camel@twins> (raw)
In-Reply-To: <E1HZ1so-0005q8-00@dorka.pomaz.szeredi.hu>
On Wed, 2007-04-04 at 11:34 +0200, Miklos Szeredi wrote:
> > Scale writeback cache per backing device, proportional to its writeout speed.
> >
> > akpm sayeth:
> > > Which problem are we trying to solve here? afaik our two uppermost
> > > problems are:
> > >
> > > a) Heavy write to queue A causes light writer to queue B to blok for a long
> > > time in balance_dirty_pages(). Even if the devices have the same speed.
> >
> > This one; esp when not the same speed. The - my usb stick makes my
> > computer suck - problem. But even on similar speed, the separation of
> > device should avoid blocking dev B when dev A is being throttled.
> >
> > The writeout speed is measure dynamically, so when it doesn't have
> > anything to write out for a while its writeback cache size goes to 0.
> >
> > Conversely, when starting up it will in the beginning act almost
> > synchronous but will quickly build up a 'fair' share of the writeback
> > cache.
>
> I'm worried about two things:
>
> 1) If the per-bdi threshold becomes smaller than the granularity of
> the per-bdi stat (due to the per-CPU counters), then things will
> break. Shouldn't there be some sanity checking for the calculated
> threshold?
I'm not sure what you're referring to.
void get_writeout_scale(struct backing_dev_info *bdi, int *scale, int *div)
{
int bits = vm_cycle_shift - 1;
unsigned long total = __global_bdi_stat(BDI_WRITEOUT_TOTAL);
unsigned long cycle = 1UL << bits;
unsigned long mask = cycle - 1;
if (bdi_cap_writeback_dirty(bdi)) {
bdi_writeout_norm(bdi);
*scale = __bdi_stat(bdi, BDI_WRITEOUT);
} else
*scale = 0;
*div = cycle + (total & mask);
}
where cycle ~ vm_total_pages
scale can be a tad off due to overstep here:
void __inc_bdi_stat(struct backing_dev_info *bdi, enum bdi_stat_item item)
{
struct bdi_per_cpu_data *pcd = &bdi->pcd[smp_processor_id()];
s8 *p = pcd->bdi_stat_diff + item;
(*p)++;
if (unlikely(*p > pcd->stat_threshold)) {
int overstep = pcd->stat_threshold / 2;
bdi_stat_add(*p + overstep, bdi, item);
*p = -overstep;
}
}
so it could be that: scale / cycle > 1
by a very small amount; however:
if (bdi) {
long long tmp = dirty;
long reserve;
int scale, div;
get_writeout_scale(bdi, &scale, &div);
tmp *= scale;
do_div(tmp, div);
reserve = dirty -
(global_bdi_stat(BDI_DIRTY) +
global_bdi_stat(BDI_WRITEBACK) +
global_bdi_stat(BDI_UNSTABLE));
if (reserve < 0)
reserve = 0;
reserve += bdi_stat(bdi, BDI_DIRTY) +
bdi_stat(bdi, BDI_WRITEBACK) +
bdi_stat(bdi, BDI_UNSTABLE);
*pbdi_dirty = min((long)tmp, reserve);
}
here we clip to 'reserve' which is the total amount of dirty threshold
not dirty by others.
> 2) The loop is sleeping in congestion_wait(WRITE), which seems wrong.
> It may well be possible that none of the queues are congested, so
> it will sleep the full .1 second. But by that time the queue may
> have become idle and is just sitting there doing nothing. Maybe
> there should be a per-bdi waitq, that is woken up, when the per-bdi
> stats are updated.
Good point, .1 seconds is a lot of time.
I'll cook up something like that if nobody beats me to it :-)
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
next prev parent reply other threads:[~2007-04-04 10:16 UTC|newest]
Thread overview: 36+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-04-03 14:40 [PATCH 0/6] per device dirty throttling -V2 Peter Zijlstra
2007-04-03 14:40 ` Peter Zijlstra
2007-04-03 14:40 ` [PATCH 1/6] mm: scalable bdi statistics counters Peter Zijlstra
2007-04-03 14:40 ` Peter Zijlstra
2007-04-04 9:20 ` Miklos Szeredi
2007-04-04 9:20 ` Miklos Szeredi
2007-04-04 9:25 ` Peter Zijlstra
2007-04-04 9:25 ` Peter Zijlstra
2007-04-03 14:40 ` [PATCH 2/6] mm: count dirty pages per BDI Peter Zijlstra
2007-04-03 14:40 ` Peter Zijlstra
2007-04-03 14:40 ` [PATCH 3/6] mm: count writeback " Peter Zijlstra
2007-04-03 14:40 ` Peter Zijlstra
2007-04-03 14:40 ` [PATCH 4/6] mm: count unstable " Peter Zijlstra
2007-04-03 14:40 ` Peter Zijlstra
2007-04-03 14:40 ` [PATCH 5/6] mm: expose BDI statistics in sysfs Peter Zijlstra
2007-04-03 14:40 ` Peter Zijlstra
2007-04-03 14:40 ` [PATCH 6/6] mm: per device dirty threshold Peter Zijlstra
2007-04-03 14:40 ` Peter Zijlstra
2007-04-04 9:34 ` Miklos Szeredi
2007-04-04 9:34 ` Miklos Szeredi
2007-04-04 10:16 ` Peter Zijlstra [this message]
2007-04-04 10:16 ` Peter Zijlstra
2007-04-04 10:29 ` Miklos Szeredi
2007-04-04 10:29 ` Miklos Szeredi
2007-04-04 11:01 ` Peter Zijlstra
2007-04-04 11:01 ` Peter Zijlstra
2007-04-04 11:12 ` Miklos Szeredi
2007-04-04 11:12 ` Miklos Szeredi
2007-04-04 12:05 ` Peter Zijlstra
2007-04-04 12:05 ` Peter Zijlstra
2007-04-04 12:32 ` Miklos Szeredi
2007-04-04 12:32 ` Miklos Szeredi
2007-04-04 12:43 ` Peter Zijlstra
2007-04-04 12:43 ` Peter Zijlstra
2007-04-04 20:03 ` Peter Zijlstra
2007-04-04 20:03 ` Peter Zijlstra
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1175681794.6483.43.camel@twins \
--to=a.p.zijlstra@chello.nl \
--cc=akpm@linux-foundation.org \
--cc=dgc@sgi.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=miklos@szeredi.hu \
--cc=neilb@suse.de \
--cc=tomoki.sekiyama.qu@hitachi.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.