From: Maxim Patlasov <mpatlasov@parallels.com>
To: Andrew Morton <akpm@linux-foundation.org>
Cc: riel@redhat.com, linux-kernel@vger.kernel.org, mhocko@suse.cz,
linux-mm@kvack.org, kosaki.motohiro@jp.fujitsu.com,
fengguang.wu@intel.com, jweiner@redhat.com
Subject: Re: [PATCH] mm/page-writeback.c: fix divide by zero in bdi_dirty_limits
Date: Mon, 14 Jul 2014 12:06:01 +0400 [thread overview]
Message-ID: <53C38F69.4070304@parallels.com> (raw)
In-Reply-To: <20140711152732.de78603744cd861497eca5dc@linux-foundation.org>
Hi Andrew,
On 07/12/2014 02:27 AM, Andrew Morton wrote:
> On Fri, 11 Jul 2014 12:18:27 +0400 Maxim Patlasov <MPatlasov@parallels.com> wrote:
>
>> Under memory pressure, it is possible for dirty_thresh, calculated by
>> global_dirty_limits() in balance_dirty_pages(), to equal zero.
> Under what circumstances? Really small values of vm_dirty_bytes?
No, I used default settings:
vm_dirty_bytes = 0;
dirty_background_bytes = 0;
vm_dirty_ratio = 20;
dirty_background_ratio = 10;
and a simple program like main() { while(1) { p = malloc(4096); mlock(p,
4096); } }. Of course, this triggers oom eventually, but immediately
before oom, the system is under hard memory pressure.
>
>> Then, if
>> strictlimit is true, bdi_dirty_limits() tries to resolve the proportion:
>>
>> bdi_bg_thresh : bdi_thresh = background_thresh : dirty_thresh
>>
>> by dividing by zero.
>>
>> ...
>>
>> --- a/mm/page-writeback.c
>> +++ b/mm/page-writeback.c
>> @@ -1306,9 +1306,9 @@ static inline void bdi_dirty_limits(struct backing_dev_info *bdi,
>> *bdi_thresh = bdi_dirty_limit(bdi, dirty_thresh);
>>
>> if (bdi_bg_thresh)
>> - *bdi_bg_thresh = div_u64((u64)*bdi_thresh *
>> - background_thresh,
>> - dirty_thresh);
>> + *bdi_bg_thresh = dirty_thresh ? div_u64((u64)*bdi_thresh *
>> + background_thresh,
>> + dirty_thresh) : 0;
> This introduces a peculiar discontinuity:
>
> if dirty_thresh==3, treat it as 3
> if dirty_thresh==2, treat it as 2
> if dirty_thresh==1, treat it as 1
> if dirty_thresh==0, treat it as infinity
No, the patch doesn't treat dirty_thresh==0 as infinity. In fact, in
that case we have equation: x : 0 = 0 : 0, and the patch resolves it as
x=0. Here is the reasoning:
1. A bdi counter is always a fraction of global one. Hence bdi_thresh is
always not greater than dirty_thresh. So far as dirty_thresh is equal to
zero, bdi_thresh is equal to zero too.
2. bdi_bg_thresh must be not greater than bdi_thresh because we want to
start background process earlier than throttling it. So far as
bdi_thresh is equal to zero, bdi_bg_thresh must be zero too.
>
> Would it not make more sense to change global_dirty_limits() to convert
> 0 to 1? With an appropriate comment, obviously.
>
>
> Or maybe the fix lies elsewhere. Please do tell us how this zero comes
> about.
>
Firstly let me explain where available_memory equal to one came from.
global_dirty_limits() calculates it by calling
global_dirtyable_memory(). The latter takes into consideration three
global counters and a global reserve. In my case corresponding values were:
NR_INACTIVE_FILE = 0
NR_ACTIVE_FILE = 0
NR_FREE_PAGES = 7006
dirty_balance_reserve = 7959.
Consequently, "x" in global_dirtyable_memory() was equal to zero, and
the function returned one. Now global_dirty_limits() assigns
available_memory to one and calculates "dirty" as a fraction of
available_memory:
dirty = (vm_dirty_ratio * available_memory) / 100;
So far as vm_drity_ratio is lesser than 100 (it is 20 by default), dirty
is calculated as zero.
As for your question about conversion 0 to 1, I think that bdi_thresh =
dirty_thresh = 0 makes natural sense: we are under strong memory
pressure, please always start background writeback and throttle process
(even if actual number of dirty pages is low). So other parts of
balance_dirty_pages machinery must handle zero thresholds properly.
Thanks,
Maxim
--
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>
WARNING: multiple messages have this Message-ID (diff)
From: Maxim Patlasov <mpatlasov@parallels.com>
To: Andrew Morton <akpm@linux-foundation.org>
Cc: <riel@redhat.com>, <linux-kernel@vger.kernel.org>,
<mhocko@suse.cz>, <linux-mm@kvack.org>,
<kosaki.motohiro@jp.fujitsu.com>, <fengguang.wu@intel.com>,
<jweiner@redhat.com>
Subject: Re: [PATCH] mm/page-writeback.c: fix divide by zero in bdi_dirty_limits
Date: Mon, 14 Jul 2014 12:06:01 +0400 [thread overview]
Message-ID: <53C38F69.4070304@parallels.com> (raw)
In-Reply-To: <20140711152732.de78603744cd861497eca5dc@linux-foundation.org>
Hi Andrew,
On 07/12/2014 02:27 AM, Andrew Morton wrote:
> On Fri, 11 Jul 2014 12:18:27 +0400 Maxim Patlasov <MPatlasov@parallels.com> wrote:
>
>> Under memory pressure, it is possible for dirty_thresh, calculated by
>> global_dirty_limits() in balance_dirty_pages(), to equal zero.
> Under what circumstances? Really small values of vm_dirty_bytes?
No, I used default settings:
vm_dirty_bytes = 0;
dirty_background_bytes = 0;
vm_dirty_ratio = 20;
dirty_background_ratio = 10;
and a simple program like main() { while(1) { p = malloc(4096); mlock(p,
4096); } }. Of course, this triggers oom eventually, but immediately
before oom, the system is under hard memory pressure.
>
>> Then, if
>> strictlimit is true, bdi_dirty_limits() tries to resolve the proportion:
>>
>> bdi_bg_thresh : bdi_thresh = background_thresh : dirty_thresh
>>
>> by dividing by zero.
>>
>> ...
>>
>> --- a/mm/page-writeback.c
>> +++ b/mm/page-writeback.c
>> @@ -1306,9 +1306,9 @@ static inline void bdi_dirty_limits(struct backing_dev_info *bdi,
>> *bdi_thresh = bdi_dirty_limit(bdi, dirty_thresh);
>>
>> if (bdi_bg_thresh)
>> - *bdi_bg_thresh = div_u64((u64)*bdi_thresh *
>> - background_thresh,
>> - dirty_thresh);
>> + *bdi_bg_thresh = dirty_thresh ? div_u64((u64)*bdi_thresh *
>> + background_thresh,
>> + dirty_thresh) : 0;
> This introduces a peculiar discontinuity:
>
> if dirty_thresh==3, treat it as 3
> if dirty_thresh==2, treat it as 2
> if dirty_thresh==1, treat it as 1
> if dirty_thresh==0, treat it as infinity
No, the patch doesn't treat dirty_thresh==0 as infinity. In fact, in
that case we have equation: x : 0 = 0 : 0, and the patch resolves it as
x=0. Here is the reasoning:
1. A bdi counter is always a fraction of global one. Hence bdi_thresh is
always not greater than dirty_thresh. So far as dirty_thresh is equal to
zero, bdi_thresh is equal to zero too.
2. bdi_bg_thresh must be not greater than bdi_thresh because we want to
start background process earlier than throttling it. So far as
bdi_thresh is equal to zero, bdi_bg_thresh must be zero too.
>
> Would it not make more sense to change global_dirty_limits() to convert
> 0 to 1? With an appropriate comment, obviously.
>
>
> Or maybe the fix lies elsewhere. Please do tell us how this zero comes
> about.
>
Firstly let me explain where available_memory equal to one came from.
global_dirty_limits() calculates it by calling
global_dirtyable_memory(). The latter takes into consideration three
global counters and a global reserve. In my case corresponding values were:
NR_INACTIVE_FILE = 0
NR_ACTIVE_FILE = 0
NR_FREE_PAGES = 7006
dirty_balance_reserve = 7959.
Consequently, "x" in global_dirtyable_memory() was equal to zero, and
the function returned one. Now global_dirty_limits() assigns
available_memory to one and calculates "dirty" as a fraction of
available_memory:
dirty = (vm_dirty_ratio * available_memory) / 100;
So far as vm_drity_ratio is lesser than 100 (it is 20 by default), dirty
is calculated as zero.
As for your question about conversion 0 to 1, I think that bdi_thresh =
dirty_thresh = 0 makes natural sense: we are under strong memory
pressure, please always start background writeback and throttle process
(even if actual number of dirty pages is low). So other parts of
balance_dirty_pages machinery must handle zero thresholds properly.
Thanks,
Maxim
next prev parent reply other threads:[~2014-07-14 8:06 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-07-11 8:18 [PATCH] mm/page-writeback.c: fix divide by zero in bdi_dirty_limits Maxim Patlasov
2014-07-11 8:18 ` Maxim Patlasov
2014-07-11 14:49 ` Rik van Riel
2014-07-11 14:49 ` Rik van Riel
2014-07-11 22:27 ` Andrew Morton
2014-07-11 22:27 ` Andrew Morton
2014-07-14 8:06 ` Maxim Patlasov [this message]
2014-07-14 8:06 ` Maxim Patlasov
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=53C38F69.4070304@parallels.com \
--to=mpatlasov@parallels.com \
--cc=akpm@linux-foundation.org \
--cc=fengguang.wu@intel.com \
--cc=jweiner@redhat.com \
--cc=kosaki.motohiro@jp.fujitsu.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=mhocko@suse.cz \
--cc=riel@redhat.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.