* [PATCH] mm/page-writeback.c: fix divide by zero in bdi_dirty_limits @ 2014-07-11 8:18 Maxim Patlasov 2014-07-11 14:49 ` Rik van Riel 2014-07-11 22:27 ` Andrew Morton 0 siblings, 2 replies; 4+ messages in thread From: Maxim Patlasov @ 2014-07-11 8:18 UTC (permalink / raw) To: akpm Cc: riel, linux-kernel, mhocko, linux-mm, kosaki.motohiro, fengguang.wu, jweiner Under memory pressure, it is possible for dirty_thresh, calculated by global_dirty_limits() in balance_dirty_pages(), to equal zero. 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. Signed-off-by: Maxim Patlasov <mpatlasov@parallels.com> --- mm/page-writeback.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mm/page-writeback.c b/mm/page-writeback.c index 518e2c3..e0c9430 100644 --- 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; /* * In order to avoid the stacked BDI deadlock we need -- 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> ^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH] mm/page-writeback.c: fix divide by zero in bdi_dirty_limits 2014-07-11 8:18 [PATCH] mm/page-writeback.c: fix divide by zero in bdi_dirty_limits Maxim Patlasov @ 2014-07-11 14:49 ` Rik van Riel 2014-07-11 22:27 ` Andrew Morton 1 sibling, 0 replies; 4+ messages in thread From: Rik van Riel @ 2014-07-11 14:49 UTC (permalink / raw) To: Maxim Patlasov, akpm Cc: linux-kernel, mhocko, linux-mm, kosaki.motohiro, fengguang.wu, jweiner -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On 07/11/2014 04:18 AM, Maxim Patlasov wrote: > Under memory pressure, it is possible for dirty_thresh, calculated > by global_dirty_limits() in balance_dirty_pages(), to equal zero. > 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. > > Signed-off-by: Maxim Patlasov <mpatlasov@parallels.com> Acked-by: Rik van Riel <riel@redhat.com> - -- All rights reversed -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/ iQEcBAEBAgAGBQJTv/mVAAoJEM553pKExN6Dw8UH/1KgQrLYDTVQIzvaXNxPwxOv xXqrWAnFf+mOflA/Tu/TqOwPUV20YSWTAuJU/NbyLSR0Ak15beCjH4ObifpgZgR+ k9lvJNHEk6XUQH0nERsHcwbNZMGtLBAvyw1oRCVXm6V1IVpbpp0IckP29KP5Ibs4 FChNNna/h7zOTpgysTtuKDO6JGuPy+sCjK5aNVH0jSTd4ENtTD1HtfkgtU/OZVyS m8afzJ0sp/A1sQGy+41ZorR3I0dAmtX3Qtx335QjrZQAy8bT3jCLBLjEHW9xQhCh afuZhfHdrXHiNh8RZnLgeFWiVzYHDc6ytoD7aZQsxaFZIlyccVRzc7SvarrT4ys= =jTrs -----END PGP SIGNATURE----- -- 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> ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] mm/page-writeback.c: fix divide by zero in bdi_dirty_limits 2014-07-11 8:18 [PATCH] mm/page-writeback.c: fix divide by zero in bdi_dirty_limits Maxim Patlasov 2014-07-11 14:49 ` Rik van Riel @ 2014-07-11 22:27 ` Andrew Morton 2014-07-14 8:06 ` Maxim Patlasov 1 sibling, 1 reply; 4+ messages in thread From: Andrew Morton @ 2014-07-11 22:27 UTC (permalink / raw) To: Maxim Patlasov Cc: riel, linux-kernel, mhocko, linux-mm, kosaki.motohiro, fengguang.wu, jweiner 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? > 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 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. -- 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> ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] mm/page-writeback.c: fix divide by zero in bdi_dirty_limits 2014-07-11 22:27 ` Andrew Morton @ 2014-07-14 8:06 ` Maxim Patlasov 0 siblings, 0 replies; 4+ messages in thread From: Maxim Patlasov @ 2014-07-14 8:06 UTC (permalink / raw) To: Andrew Morton Cc: riel, linux-kernel, mhocko, linux-mm, kosaki.motohiro, fengguang.wu, jweiner 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> ^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2014-07-14 8:06 UTC | newest] Thread overview: 4+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2014-07-11 8:18 [PATCH] mm/page-writeback.c: fix divide by zero in bdi_dirty_limits Maxim Patlasov 2014-07-11 14:49 ` Rik van Riel 2014-07-11 22:27 ` Andrew Morton 2014-07-14 8:06 ` Maxim Patlasov
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).